Migrate aurora-sharp-desktop
This commit is contained in:
1 parent
d6496355a9
commit
b8c0dadf91
186 files changed
+8521
No files matched your search
@@ -0,0 +1,351 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
start*.sh
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,11 @@
|
|||||||
|
.primaryColor {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accentColor {
|
||||||
|
background-color: #181818;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondAccentColor {
|
||||||
|
background-color: #303030
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Application
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:converters="clr-namespace:Aurora.Design.Converters"
|
||||||
|
x:Class="Aurora.App">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary><!-- GENERAL COLORS -->
|
||||||
|
<Color
|
||||||
|
x:Key="WhiteColor">#FFFFFF</Color>
|
||||||
|
<Color
|
||||||
|
x:Key="BlackColor">#000000</Color><!-- THEME COLORS -->
|
||||||
|
<Color
|
||||||
|
x:Key="AccentColor">#F5C210</Color>
|
||||||
|
<Color
|
||||||
|
x:Key="ToolbarColor">#151C25</Color>
|
||||||
|
<Color
|
||||||
|
x:Key="BackgroundColor">#1E2634</Color>
|
||||||
|
<Color
|
||||||
|
x:Key="DarkBackgroundColor">#151C25</Color>
|
||||||
|
<Color
|
||||||
|
x:Key="MenuBackgroundColor">#44545C</Color><!-- CONVERTERS -->
|
||||||
|
<converters:InverseBoolConverter
|
||||||
|
x:Key="InverseBoolConverter"/>
|
||||||
|
<converters:ToUpperConverter
|
||||||
|
x:Key="ToUpperConverter"/>
|
||||||
|
<StyleSheet
|
||||||
|
Source="App.css"/>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using Aurora.Design.Views.Main;
|
||||||
|
using Aurora.Design.Views.Albums;
|
||||||
|
using Aurora.Design.Views.Artists;
|
||||||
|
using Aurora.Design.Views.Party;
|
||||||
|
using Aurora.Design.Views.Profile;
|
||||||
|
using Aurora.Design.Views.Songs;
|
||||||
|
using Aurora.Design.Views.Stations;
|
||||||
|
using Aurora.Services.EventManager;
|
||||||
|
using Aurora.Services.Server;
|
||||||
|
using Aurora.Services.Client;
|
||||||
|
using Autofac;
|
||||||
|
using LibVLCSharp.Shared;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
using Aurora.Services.Player;
|
||||||
|
using Aurora.Services.Settings;
|
||||||
|
using Aurora.Services.Library;
|
||||||
|
|
||||||
|
namespace Aurora
|
||||||
|
{
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
private static IContainer _container;
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
Core.Initialize();
|
||||||
|
|
||||||
|
//Register DI
|
||||||
|
ContainerBuilder _builder = new ContainerBuilder();
|
||||||
|
// _builder.RegisterInstance<IPlayer>(new PlayerService()).SingleInstance();
|
||||||
|
_builder.RegisterType<PlayerService>().As<IPlayer>().SingleInstance();
|
||||||
|
_builder.RegisterType<SettingsService>().As<ISettingsService>().SingleInstance();
|
||||||
|
_builder.RegisterType<LibraryService>().As<ILibraryService>().SingleInstance();
|
||||||
|
_builder.RegisterType<EventManager>().As<IEventManager>().SingleInstance();
|
||||||
|
_builder.RegisterType<ServerService>().As<IServerService>().SingleInstance();
|
||||||
|
_builder.RegisterType<ClientService>().As<IClientService>().SingleInstance();
|
||||||
|
_builder.RegisterType<MainView>().SingleInstance();
|
||||||
|
_builder.RegisterType<AlbumsViewModel>();
|
||||||
|
_builder.RegisterType<ArtistsViewModel>();
|
||||||
|
_builder.RegisterType<PartyViewModel>();
|
||||||
|
_builder.RegisterType<ProfileViewModel>();
|
||||||
|
_builder.RegisterType<SongsViewModel>();
|
||||||
|
_builder.RegisterType<StationsViewModel>();
|
||||||
|
|
||||||
|
// _builder.RegisterInstance<ISettingsService>(new SettingsService()).SingleInstance();
|
||||||
|
_container = _builder.Build();
|
||||||
|
|
||||||
|
MainPage = _container.Resolve<MainView>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IContainer Container
|
||||||
|
{
|
||||||
|
get { return _container; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStart()
|
||||||
|
{
|
||||||
|
// Handle when your app starts
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnSleep()
|
||||||
|
{
|
||||||
|
// Handle when your app sleeps
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResume()
|
||||||
|
{
|
||||||
|
// Handle when your app resumes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
using Xamarin.Forms.Xaml;
|
||||||
|
|
||||||
|
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<ProduceAssemblyReference>true</ProduceAssemblyReference>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Xamarin.Forms" Version="4.3.0.991211" />
|
||||||
|
<PackageReference Include="Xamarin.Essentials" Version="1.3.1" />
|
||||||
|
<PackageReference Include="taglib-sharp-netstandard2.0" Version="2.1.0" />
|
||||||
|
<PackageReference Include="LibVLCSharp.Forms" Version="3.3.1" />
|
||||||
|
<PackageReference Include="VideoLAN.LibVLC.Mac" Version="3.1.3.1" />
|
||||||
|
<PackageReference Include="Grpc" Version="2.25.0" />
|
||||||
|
<PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssests="All">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Google.Protobuf" Version="3.10.1" />
|
||||||
|
<PackageReference Include="Xam.Plugins.Settings" Version="3.1.1" />
|
||||||
|
<PackageReference Include="Sharpnado.Forms.HorizontalListView" Version="1.3.0" />
|
||||||
|
<PackageReference Include="DLToolkit.Forms.Controls.FlowListView" Version="2.0.11" />
|
||||||
|
<PackageReference Include="CarouselView.FormsPlugin" Version="5.2.0" />
|
||||||
|
<PackageReference Include="Autofac" Version="5.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Design\" />
|
||||||
|
<Folder Include="Design\Components\" />
|
||||||
|
<Folder Include="Design\Views\" />
|
||||||
|
<Folder Include="Design\Views\Songs\" />
|
||||||
|
<Folder Include="Design\Views\MainView\" />
|
||||||
|
<Folder Include="Design\Behaviors\" />
|
||||||
|
<Folder Include="Design\Components\NavigationMenu\" />
|
||||||
|
<Folder Include="Design\Views\Albums\" />
|
||||||
|
<Folder Include="Design\Views\Artists\" />
|
||||||
|
<Folder Include="Design\Views\Stations\" />
|
||||||
|
<Folder Include="Utils\" />
|
||||||
|
<Folder Include="Models\" />
|
||||||
|
<Folder Include="Services\" />
|
||||||
|
<Folder Include="Design\Views\Party\" />
|
||||||
|
<Folder Include="Design\Components\MemberList\" />
|
||||||
|
<Folder Include="Design\Components\Library\" />
|
||||||
|
<Folder Include="Design\Views\Profile\" />
|
||||||
|
<Folder Include="Design\Components\DataGrid\" />
|
||||||
|
<Folder Include="Resources\" />
|
||||||
|
<Folder Include="Design\Extensions\" />
|
||||||
|
<Folder Include="Design\Components\ImageButton\" />
|
||||||
|
<Folder Include="Design\Components\Dialogs\" />
|
||||||
|
<Folder Include="Design\Views\Party\NewPartyDialog\" />
|
||||||
|
<Folder Include="Design\Components\TabView\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Design\Behaviors\DeselectItemBehaviorBase.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Design\Components\MusicPlayer\Player.xaml.cs">
|
||||||
|
<DependentUpon>Player.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="Proto\general.proto" />
|
||||||
|
<Protobuf Include="Proto\party.proto" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Resources\backward.png" />
|
||||||
|
<EmbeddedResource Include="Resources\forwards.png" />
|
||||||
|
<EmbeddedResource Include="Resources\like.png" />
|
||||||
|
<EmbeddedResource Include="Resources\play.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="Design\Components\NavigationMenu\NavigationMenu.css">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Design\Resources\unselected.png" />
|
||||||
|
<None Remove="Design\Components\MediaPlayer\play.png" />
|
||||||
|
<None Remove="Resources\backward.png" />
|
||||||
|
<None Remove="Resources\forwards.png" />
|
||||||
|
<None Remove="Resources\like.png" />
|
||||||
|
<None Remove="Resources\play.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Behaviors
|
||||||
|
{
|
||||||
|
public class BehaviorBase<T> : Behavior<T> where T : BindableObject
|
||||||
|
{
|
||||||
|
public T AssociatedObject { get; private set; }
|
||||||
|
|
||||||
|
protected override void OnAttachedTo(T bindable)
|
||||||
|
{
|
||||||
|
base.OnAttachedTo(bindable);
|
||||||
|
AssociatedObject = bindable;
|
||||||
|
|
||||||
|
if (bindable.BindingContext != null)
|
||||||
|
{
|
||||||
|
BindingContext = bindable.BindingContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
bindable.BindingContextChanged += OnBindingContextChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDetachingFrom(T bindable)
|
||||||
|
{
|
||||||
|
base.OnDetachingFrom(bindable);
|
||||||
|
bindable.BindingContextChanged -= OnBindingContextChanged;
|
||||||
|
AssociatedObject = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnBindingContextChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
OnBindingContextChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnBindingContextChanged()
|
||||||
|
{
|
||||||
|
base.OnBindingContextChanged();
|
||||||
|
BindingContext = AssociatedObject.BindingContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Behaviors
|
||||||
|
{
|
||||||
|
public class EventToCommandBehavior : BehaviorBase<View>
|
||||||
|
{
|
||||||
|
Delegate eventHandler;
|
||||||
|
|
||||||
|
public static readonly BindableProperty EventNameProperty = BindableProperty.Create("EventName", typeof(string), typeof(EventToCommandBehavior), null, propertyChanged: OnEventNameChanged);
|
||||||
|
public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(EventToCommandBehavior), null);
|
||||||
|
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(EventToCommandBehavior), null);
|
||||||
|
public static readonly BindableProperty InputConverterProperty = BindableProperty.Create("Converter", typeof(IValueConverter), typeof(EventToCommandBehavior), null);
|
||||||
|
|
||||||
|
public string EventName
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(EventNameProperty); }
|
||||||
|
set { SetValue(EventNameProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICommand Command
|
||||||
|
{
|
||||||
|
get { return (ICommand)GetValue(CommandProperty); }
|
||||||
|
set { SetValue(CommandProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public object CommandParameter
|
||||||
|
{
|
||||||
|
get { return GetValue(CommandParameterProperty); }
|
||||||
|
set { SetValue(CommandParameterProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IValueConverter Converter
|
||||||
|
{
|
||||||
|
get { return (IValueConverter)GetValue(InputConverterProperty); }
|
||||||
|
set { SetValue(InputConverterProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnAttachedTo(View bindable)
|
||||||
|
{
|
||||||
|
base.OnAttachedTo(bindable);
|
||||||
|
RegisterEvent(EventName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDetachingFrom(View bindable)
|
||||||
|
{
|
||||||
|
DeregisterEvent(EventName);
|
||||||
|
base.OnDetachingFrom(bindable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterEvent(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
|
||||||
|
if (eventInfo == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format("EventToCommandBehavior: Can't register the '{0}' event.", EventName));
|
||||||
|
}
|
||||||
|
MethodInfo methodInfo = typeof(EventToCommandBehavior).GetTypeInfo().GetDeclaredMethod("OnEvent");
|
||||||
|
eventHandler = methodInfo.CreateDelegate(eventInfo.EventHandlerType, this);
|
||||||
|
eventInfo.AddEventHandler(AssociatedObject, eventHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeregisterEvent(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventHandler == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name);
|
||||||
|
if (eventInfo == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format("EventToCommandBehavior: Can't de-register the '{0}' event.", EventName));
|
||||||
|
}
|
||||||
|
eventInfo.RemoveEventHandler(AssociatedObject, eventHandler);
|
||||||
|
eventHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEvent(object sender, object eventArgs)
|
||||||
|
{
|
||||||
|
if (Command == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
object resolvedParameter;
|
||||||
|
if (CommandParameter != null)
|
||||||
|
{
|
||||||
|
resolvedParameter = CommandParameter;
|
||||||
|
}
|
||||||
|
else if (Converter != null)
|
||||||
|
{
|
||||||
|
resolvedParameter = Converter.Convert(eventArgs, typeof(object), null, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resolvedParameter = eventArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Command.CanExecute(resolvedParameter))
|
||||||
|
{
|
||||||
|
Command.Execute(resolvedParameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnEventNameChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
|
{
|
||||||
|
var behavior = (EventToCommandBehavior)bindable;
|
||||||
|
if (behavior.AssociatedObject == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string oldEventName = (string)oldValue;
|
||||||
|
string newEventName = (string)newValue;
|
||||||
|
|
||||||
|
behavior.DeregisterEvent(oldEventName);
|
||||||
|
behavior.RegisterEvent(newEventName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public sealed class ColumnCollection : List<DataGridColumn>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Grid
|
||||||
|
x:Name="self"
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
x:Class="Aurora.Design.Components.DataGrid.DataGrid"
|
||||||
|
Padding="0"
|
||||||
|
RowSpacing="0">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition
|
||||||
|
Height="Auto"/>
|
||||||
|
<RowDefinition
|
||||||
|
Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid
|
||||||
|
x:Name="_headerView"
|
||||||
|
RowSpacing="0">
|
||||||
|
<Grid.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<!--Default Header Style-->
|
||||||
|
<Style
|
||||||
|
x:Key="HeaderDefaultStyle"
|
||||||
|
TargetType="Label">
|
||||||
|
<Setter
|
||||||
|
Property="FontSize"
|
||||||
|
Value="{Binding HeaderFontSize, Source={x:Reference self}}"/>
|
||||||
|
<Setter
|
||||||
|
Property="FontAttributes"
|
||||||
|
Value="Bold"/>
|
||||||
|
<Setter
|
||||||
|
Property="HorizontalOptions"
|
||||||
|
Value="Center"/>
|
||||||
|
<Setter
|
||||||
|
Property="VerticalOptions"
|
||||||
|
Value="Center"/>
|
||||||
|
<Setter
|
||||||
|
Property="TextColor"
|
||||||
|
Value="{Binding HeaderTextColor,Source={x:Reference self}}"/>
|
||||||
|
<Setter
|
||||||
|
Property="LineBreakMode"
|
||||||
|
Value="WordWrap"/>
|
||||||
|
</Style>
|
||||||
|
<Style
|
||||||
|
TargetType="Grid">
|
||||||
|
<Setter
|
||||||
|
Property="BackgroundColor"
|
||||||
|
Value="{Binding HeaderBackground,Source={x:Reference self}}"/>
|
||||||
|
</Style>
|
||||||
|
<Style
|
||||||
|
x:Key="ImageStyleBase"
|
||||||
|
TargetType="Image">
|
||||||
|
<Setter
|
||||||
|
Property="Aspect"
|
||||||
|
Value="AspectFill"/>
|
||||||
|
<Setter
|
||||||
|
Property="VerticalOptions"
|
||||||
|
Value="Center"/>
|
||||||
|
<Setter
|
||||||
|
Property="HorizontalOptions"
|
||||||
|
Value="Center"/>
|
||||||
|
<Setter
|
||||||
|
Property="HeightRequest"
|
||||||
|
Value="5"/>
|
||||||
|
<Setter
|
||||||
|
Property="WidthRequest"
|
||||||
|
Value="9"/>
|
||||||
|
<Setter
|
||||||
|
Property="Margin"
|
||||||
|
Value="0,0,4,0"/>
|
||||||
|
</Style>
|
||||||
|
<Style
|
||||||
|
x:Key="AscendingIconStyle"
|
||||||
|
TargetType="Image"
|
||||||
|
BasedOn="{StaticResource ImageStyleBase}">
|
||||||
|
<Setter
|
||||||
|
Property="Source"
|
||||||
|
Value="{Binding AscendingIcon, Source={x:Reference self}}"/>
|
||||||
|
</Style>
|
||||||
|
<Style
|
||||||
|
x:Key="DescendingIconStyle"
|
||||||
|
TargetType="Image"
|
||||||
|
BasedOn="{StaticResource ImageStyleBase}">
|
||||||
|
<Setter
|
||||||
|
Property="Source"
|
||||||
|
Value="{Binding DescendingIcon, Source={x:Reference self}}"/>
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Grid.Resources>
|
||||||
|
</Grid>
|
||||||
|
<ListView x:Name="DataList" Grid.Row="1" BackgroundColor="#222222" />
|
||||||
|
<ContentView
|
||||||
|
x:Name="_noDataView"
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
IsVisible="False"/>
|
||||||
|
</Grid>
|
||||||
@@ -0,0 +1,756 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
using Aurora.Utils;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public partial class DataGrid : Grid
|
||||||
|
{
|
||||||
|
#region Private Fields
|
||||||
|
private ObservableCollection<object> _internalItems;
|
||||||
|
|
||||||
|
private Dictionary<int, SortingOrder> _sortingOrders;
|
||||||
|
|
||||||
|
#endregion Fields
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
public DataGrid() : this(ListViewCachingStrategy.RetainElement)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataGrid(ListViewCachingStrategy cachingStrategy)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
BackgroundColor = Color.Transparent;
|
||||||
|
|
||||||
|
_sortingOrders = new Dictionary<int, SortingOrder>();
|
||||||
|
|
||||||
|
DataList.ItemTemplate = new DataGridRowTemplateSelector();
|
||||||
|
|
||||||
|
DataList.ItemSelected += (s, e) =>
|
||||||
|
{
|
||||||
|
if (SelectionEnabled)
|
||||||
|
{
|
||||||
|
SelectedItem = DataList.SelectedItem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DataList.SelectedItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemSelected?.Invoke(this, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
DataList.Refreshing += (s, e) =>
|
||||||
|
{
|
||||||
|
Refreshing?.Invoke(this, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
DataList.SetBinding(ListView.RowHeightProperty, new Binding("RowHeight", source: this));
|
||||||
|
}
|
||||||
|
#endregion Constructor
|
||||||
|
|
||||||
|
#region Public Fields
|
||||||
|
public event EventHandler Refreshing;
|
||||||
|
public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
|
||||||
|
|
||||||
|
#endregion Public Fields
|
||||||
|
|
||||||
|
#region Bindable properties
|
||||||
|
public static readonly BindableProperty ActiveRowColorProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(ActiveRowColor),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(DataGrid),
|
||||||
|
Color.FromRgb(128, 144, 160),
|
||||||
|
coerceValue: (bindable, value) =>
|
||||||
|
{
|
||||||
|
if (!(bindable as DataGrid).SelectionEnabled)
|
||||||
|
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set ActiveRowColor");
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty HeaderBackgroundProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(HeaderBackground),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(DataGrid),
|
||||||
|
Color.White,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if (self._headerView != null && !self.HeaderBordersVisible)
|
||||||
|
self._headerView.BackgroundColor = (Color)newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty BorderColorProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(BorderColor),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(DataGrid),
|
||||||
|
Color.Black,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if (self.HeaderBordersVisible)
|
||||||
|
self._headerView.BackgroundColor = (Color)newValue;
|
||||||
|
|
||||||
|
if (self.Columns != null && self.ItemsSource != null)
|
||||||
|
self.Reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty RowsBackgroundColorPaletteProperty =
|
||||||
|
BindableProperty.Create(nameof(RowsBackgroundColorPalette),
|
||||||
|
typeof(IColorProvider),
|
||||||
|
typeof(DataGrid),
|
||||||
|
new PaletteCollection { default(Color) },
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if (self.Columns != null && self.ItemsSource != null)
|
||||||
|
self.Reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty RowsTextColorPaletteProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(RowsTextColorPalette),
|
||||||
|
typeof(IColorProvider),
|
||||||
|
typeof(DataGrid),
|
||||||
|
new PaletteCollection { Color.Black },
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if (self.Columns != null && self.ItemsSource != null)
|
||||||
|
self.Reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty ColumnsProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(Columns),
|
||||||
|
typeof(ColumnCollection),
|
||||||
|
typeof(DataGrid),
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
(bindable as DataGrid).InitHeaderView();
|
||||||
|
},
|
||||||
|
defaultValueCreator: bindable => { return new ColumnCollection(); }
|
||||||
|
);
|
||||||
|
|
||||||
|
public static BindableProperty ItemsSourceProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
propertyName: nameof(ItemsSource),
|
||||||
|
returnType: typeof(IEnumerable),
|
||||||
|
declaringType: typeof(DataGrid),
|
||||||
|
defaultBindingMode: BindingMode.TwoWay,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
DataGrid self = bindable as DataGrid;
|
||||||
|
//ObservableCollection Tracking
|
||||||
|
if (oldValue != null && oldValue is INotifyCollectionChanged)
|
||||||
|
{
|
||||||
|
(oldValue as INotifyCollectionChanged).CollectionChanged -= self.HandleItemsSourceCollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newValue != null && newValue is INotifyCollectionChanged)
|
||||||
|
{
|
||||||
|
(newValue as INotifyCollectionChanged).CollectionChanged += self.HandleItemsSourceCollectionChanged;
|
||||||
|
|
||||||
|
self.InternalItems = new ObservableCollection<object>(((IEnumerable<object>)newValue));
|
||||||
|
//Assign listview item source
|
||||||
|
self.DataList.ItemsSource = self.InternalItems;
|
||||||
|
self.DataList.SetBinding(ListView.ItemsSourceProperty, new Binding("ItemsSource", source: self));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.SelectedItem != null && !self.InternalItems.Contains(self.SelectedItem))
|
||||||
|
{
|
||||||
|
self.SelectedItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.NoDataView != null)
|
||||||
|
{
|
||||||
|
if (self.ItemsSource == null || self.InternalItems.Count() == 0)
|
||||||
|
{
|
||||||
|
self._noDataView.IsVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (self._noDataView.IsVisible)
|
||||||
|
{
|
||||||
|
self._noDataView.IsVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
private void HandleItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (e.NewItems != null)
|
||||||
|
{
|
||||||
|
foreach (object item in e.NewItems)
|
||||||
|
{
|
||||||
|
InternalItems.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.OldItems != null)
|
||||||
|
{
|
||||||
|
foreach (object item in e.OldItems)
|
||||||
|
{
|
||||||
|
InternalItems.Remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (SelectedItem != null && !InternalItems.Contains(SelectedItem))
|
||||||
|
{
|
||||||
|
SelectedItem = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly BindableProperty RowHeightProperty =
|
||||||
|
BindableProperty.Create(nameof(RowHeight), typeof(int), typeof(DataGrid), 40,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
self.DataList.RowHeight = (int)newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
public static readonly BindableProperty HeaderHeightProperty =
|
||||||
|
BindableProperty.Create(nameof(HeaderHeight), typeof(int), typeof(DataGrid), 40,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
self._headerView.HeightRequest = (int)newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty IsSortableProperty =
|
||||||
|
BindableProperty.Create(nameof(IsSortable), typeof(bool), typeof(DataGrid), true);
|
||||||
|
|
||||||
|
public static readonly BindableProperty FontSizeProperty =
|
||||||
|
BindableProperty.Create(nameof(FontSize), typeof(double), typeof(DataGrid), 13.0);
|
||||||
|
|
||||||
|
public static readonly BindableProperty FontFamilyProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(FontFamily),
|
||||||
|
typeof(string),
|
||||||
|
typeof(DataGrid),
|
||||||
|
Font.Default.FontFamily);
|
||||||
|
|
||||||
|
public static readonly BindableProperty SelectedItemProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(SelectedItem),
|
||||||
|
typeof(object),
|
||||||
|
typeof(DataGrid),
|
||||||
|
null,
|
||||||
|
BindingMode.TwoWay,
|
||||||
|
coerceValue: (bindable, value) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if (!self.SelectionEnabled && value != null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set SelectedItem");
|
||||||
|
}
|
||||||
|
if (self.InternalItems != null && self.InternalItems.Contains(value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if (self.DataList.SelectedItem != newValue)
|
||||||
|
{
|
||||||
|
self.DataList.SelectedItem = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
public static readonly BindableProperty SelectionEnabledProperty =
|
||||||
|
BindableProperty.Create(nameof(SelectionEnabled), typeof(bool), typeof(DataGrid), true,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if (!self.SelectionEnabled && self.SelectedItem != null)
|
||||||
|
{
|
||||||
|
self.SelectedItem = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty PullToRefreshCommandProperty =
|
||||||
|
BindableProperty.Create(nameof(PullToRefreshCommand), typeof(ICommand), typeof(DataGrid), null,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if (newValue == null)
|
||||||
|
{
|
||||||
|
self.DataList.IsPullToRefreshEnabled = false;
|
||||||
|
self.DataList.RefreshCommand = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.DataList.IsPullToRefreshEnabled = true;
|
||||||
|
self.DataList.RefreshCommand = newValue as ICommand;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty IsRefreshingProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(IsRefreshing),
|
||||||
|
typeof(bool),
|
||||||
|
typeof(DataGrid),
|
||||||
|
false,
|
||||||
|
BindingMode.TwoWay,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
(bindable as DataGrid).DataList.IsRefreshing = (bool)newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty BorderThicknessProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(BorderThickness),
|
||||||
|
typeof(Thickness),
|
||||||
|
typeof(DataGrid),
|
||||||
|
new Thickness(1),
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
(bindable as DataGrid)._headerView.ColumnSpacing = ((Thickness)newValue).HorizontalThickness / 2;
|
||||||
|
(bindable as DataGrid)._headerView.Padding = ((Thickness)newValue).HorizontalThickness / 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty HeaderBordersVisibleProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(HeaderBordersVisible),
|
||||||
|
typeof(bool),
|
||||||
|
typeof(DataGrid),
|
||||||
|
true,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) => (bindable as DataGrid)._headerView.BackgroundColor = (bool)newValue ? (bindable as DataGrid).BorderColor : (bindable as DataGrid).HeaderBackground);
|
||||||
|
|
||||||
|
public static readonly BindableProperty SortedColumnIndexProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(SortedColumnIndex),
|
||||||
|
typeof(SortData),
|
||||||
|
typeof(DataGrid),
|
||||||
|
null,
|
||||||
|
BindingMode.TwoWay,
|
||||||
|
validateValue: (bindable, v) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
var sData = (SortData)v;
|
||||||
|
|
||||||
|
return
|
||||||
|
sData == null || //setted to null
|
||||||
|
self.Columns == null || // Columns binded but not setted
|
||||||
|
self.Columns.Count == 0 || //columns not setted yet
|
||||||
|
(sData.Index < self.Columns.Count && self.Columns.ElementAt(sData.Index).SortingEnabled);
|
||||||
|
},
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if (oldValue != newValue)
|
||||||
|
self.SortItems((SortData)newValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
public static readonly BindableProperty HeaderLabelStyleProperty =
|
||||||
|
BindableProperty.Create(nameof(HeaderLabelStyle), typeof(Style), typeof(DataGrid));
|
||||||
|
|
||||||
|
public static readonly BindableProperty AscendingIconProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(AscendingIcon),
|
||||||
|
typeof(ImageSource),
|
||||||
|
typeof(DataGrid),
|
||||||
|
ImageSource.FromResource("Xamarin.Forms.DataGrid.up.png",
|
||||||
|
typeof(DataGrid).GetTypeInfo().Assembly));
|
||||||
|
|
||||||
|
public static readonly BindableProperty DescendingIconProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(DescendingIcon),
|
||||||
|
typeof(ImageSource),
|
||||||
|
typeof(DataGrid),
|
||||||
|
ImageSource.FromResource("Xamarin.Forms.DataGrid.down.png",
|
||||||
|
typeof(DataGrid).GetTypeInfo().Assembly));
|
||||||
|
|
||||||
|
public static readonly BindableProperty DescendingIconStyleProperty =
|
||||||
|
BindableProperty.Create(nameof(DescendingIconStyle), typeof(Style), typeof(DataGrid), null,
|
||||||
|
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
var style = (newValue as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty);
|
||||||
|
if (style != null)
|
||||||
|
{
|
||||||
|
if (style.Value is string vs)
|
||||||
|
self.DescendingIcon = ImageSource.FromFile(vs);
|
||||||
|
else
|
||||||
|
self.DescendingIcon = (ImageSource)style.Value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty AscendingIconStyleProperty =
|
||||||
|
BindableProperty.Create(nameof(AscendingIconStyle), typeof(Style), typeof(DataGrid), null,
|
||||||
|
coerceValue: (bindable, v) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
var self = bindable as DataGrid;
|
||||||
|
if ((newValue as Style).Setters.Any(x => x.Property == Image.SourceProperty))
|
||||||
|
{
|
||||||
|
var style = (newValue as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty);
|
||||||
|
if (style != null)
|
||||||
|
{
|
||||||
|
if (style.Value is string vs)
|
||||||
|
self.AscendingIcon = ImageSource.FromFile(vs);
|
||||||
|
else
|
||||||
|
self.AscendingIcon = (ImageSource)style.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty NoDataViewProperty =
|
||||||
|
BindableProperty.Create(nameof(NoDataView), typeof(View), typeof(DataGrid),
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
if (oldValue != newValue)
|
||||||
|
(bindable as DataGrid)._noDataView.Content = newValue as View;
|
||||||
|
});
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public Color ActiveRowColor
|
||||||
|
{
|
||||||
|
get { return (Color)GetValue(ActiveRowColorProperty); }
|
||||||
|
set { SetValue(ActiveRowColorProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color HeaderBackground
|
||||||
|
{
|
||||||
|
get { return (Color)GetValue(HeaderBackgroundProperty); }
|
||||||
|
set { SetValue(HeaderBackgroundProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("Please use HeaderLabelStyle", true)]
|
||||||
|
public Color HeaderTextColor
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color BorderColor
|
||||||
|
{
|
||||||
|
get { return (Color)GetValue(BorderColorProperty); }
|
||||||
|
set { SetValue(BorderColorProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IColorProvider RowsBackgroundColorPalette
|
||||||
|
{
|
||||||
|
get { return (IColorProvider)GetValue(RowsBackgroundColorPaletteProperty); }
|
||||||
|
set { SetValue(RowsBackgroundColorPaletteProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IColorProvider RowsTextColorPalette
|
||||||
|
{
|
||||||
|
get { return (IColorProvider)GetValue(RowsTextColorPaletteProperty); }
|
||||||
|
set { SetValue(RowsTextColorPaletteProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable ItemsSource
|
||||||
|
{
|
||||||
|
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
|
||||||
|
set { SetValue(ItemsSourceProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ObservableCollection<object> InternalItems
|
||||||
|
{
|
||||||
|
get { return _internalItems; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _internalItems)
|
||||||
|
{
|
||||||
|
_internalItems = value;
|
||||||
|
if (IsSortable && SortedColumnIndex != null)
|
||||||
|
{
|
||||||
|
SortItems(SortedColumnIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataList.ItemsSource = _internalItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnCollection Columns
|
||||||
|
{
|
||||||
|
get { return (ColumnCollection)GetValue(ColumnsProperty); }
|
||||||
|
set { SetValue(ColumnsProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public double FontSize
|
||||||
|
{
|
||||||
|
get { return (double)GetValue(FontSizeProperty); }
|
||||||
|
set { SetValue(FontSizeProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("Please use HeaderLabelStyle", true)]
|
||||||
|
public double HeaderFontSize
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FontFamily
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(FontFamilyProperty); }
|
||||||
|
set { SetValue(FontFamilyProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RowHeight
|
||||||
|
{
|
||||||
|
get { return (int)GetValue(RowHeightProperty); }
|
||||||
|
set { SetValue(RowHeightProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int HeaderHeight
|
||||||
|
{
|
||||||
|
get { return (int)GetValue(HeaderHeightProperty); }
|
||||||
|
set { SetValue(HeaderHeightProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSortable
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(IsSortableProperty); }
|
||||||
|
set { SetValue(IsSortableProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SelectionEnabled
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(SelectionEnabledProperty); }
|
||||||
|
set { SetValue(SelectionEnabledProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public object SelectedItem
|
||||||
|
{
|
||||||
|
get { return GetValue(SelectedItemProperty); }
|
||||||
|
set { SetValue(SelectedItemProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICommand PullToRefreshCommand
|
||||||
|
{
|
||||||
|
get { return (ICommand)GetValue(PullToRefreshCommandProperty); }
|
||||||
|
set { SetValue(PullToRefreshCommandProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRefreshing
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(IsRefreshingProperty); }
|
||||||
|
set { SetValue(IsRefreshingProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thickness BorderThickness
|
||||||
|
{
|
||||||
|
get { return (Thickness)GetValue(BorderThicknessProperty); }
|
||||||
|
set { SetValue(BorderThicknessProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HeaderBordersVisible
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(HeaderBordersVisibleProperty); }
|
||||||
|
set { SetValue(HeaderBordersVisibleProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortData SortedColumnIndex
|
||||||
|
{
|
||||||
|
get { return (SortData)GetValue(SortedColumnIndexProperty); }
|
||||||
|
set { SetValue(SortedColumnIndexProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Style HeaderLabelStyle
|
||||||
|
{
|
||||||
|
get { return (Style)GetValue(HeaderLabelStyleProperty); }
|
||||||
|
set { SetValue(HeaderLabelStyleProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageSource AscendingIcon
|
||||||
|
{
|
||||||
|
get { return (ImageSource)GetValue(AscendingIconProperty); }
|
||||||
|
set { SetValue(AscendingIconProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageSource DescendingIcon
|
||||||
|
{
|
||||||
|
get { return (ImageSource)GetValue(DescendingIconProperty); }
|
||||||
|
set { SetValue(DescendingIconProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Style AscendingIconStyle
|
||||||
|
{
|
||||||
|
get { return (Style)GetValue(AscendingIconStyleProperty); }
|
||||||
|
set { SetValue(AscendingIconStyleProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Style DescendingIconStyle
|
||||||
|
{
|
||||||
|
get { return (Style)GetValue(DescendingIconStyleProperty); }
|
||||||
|
set { SetValue(DescendingIconStyleProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public View NoDataView
|
||||||
|
{
|
||||||
|
get { return (View)GetValue(NoDataViewProperty); }
|
||||||
|
set { SetValue(NoDataViewProperty, value); }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UI Methods
|
||||||
|
protected override void OnParentSet()
|
||||||
|
{
|
||||||
|
base.OnParentSet();
|
||||||
|
InitHeaderView();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnBindingContextChanged()
|
||||||
|
{
|
||||||
|
base.OnBindingContextChanged();
|
||||||
|
SetColumnsBindingContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private void Reload()
|
||||||
|
{
|
||||||
|
InternalItems = new ObservableCollection<object>(_internalItems);
|
||||||
|
}
|
||||||
|
private void SortItems(SortData sData)
|
||||||
|
{
|
||||||
|
if (InternalItems == null || sData.Index >= Columns.Count || !Columns[sData.Index].SortingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var items = InternalItems;
|
||||||
|
var column = Columns[sData.Index];
|
||||||
|
SortingOrder order = sData.Order;
|
||||||
|
|
||||||
|
if (!IsSortable)
|
||||||
|
throw new InvalidOperationException("This DataGrid is not sortable");
|
||||||
|
else if (column.PropertyName == null)
|
||||||
|
throw new InvalidOperationException("Please set the PropertyName property of Column");
|
||||||
|
|
||||||
|
//Sort
|
||||||
|
// if (order == SortingOrder.Descendant)
|
||||||
|
// items = items.OrderByDescending(x => ReflectionUtils.GetValueByPath(x, column.PropertyName)).ToList();
|
||||||
|
// else
|
||||||
|
// items = items.OrderBy(x => ReflectionUtils.GetValueByPath(x, column.PropertyName)).ToList();
|
||||||
|
|
||||||
|
column.SortingIcon.Style = (order == SortingOrder.Descendant) ?
|
||||||
|
AscendingIconStyle ?? (Style)_headerView.Resources["DescendingIconStyle"] :
|
||||||
|
DescendingIconStyle ?? (Style)_headerView.Resources["AscendingIconStyle"];
|
||||||
|
|
||||||
|
//Support DescendingIcon property (if setted)
|
||||||
|
if (!column.SortingIcon.Style.Setters.Any(x => x.Property == Image.SourceProperty))
|
||||||
|
{
|
||||||
|
if (order == SortingOrder.Descendant && DescendingIconProperty.DefaultValue != DescendingIcon)
|
||||||
|
column.SortingIcon.Source = DescendingIcon;
|
||||||
|
if (order == SortingOrder.Ascendant && AscendingIconProperty.DefaultValue != AscendingIcon)
|
||||||
|
column.SortingIcon.Source = AscendingIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Columns.Count; i++)
|
||||||
|
{
|
||||||
|
if (i != sData.Index)
|
||||||
|
{
|
||||||
|
if (Columns[i].SortingIcon.Style != null)
|
||||||
|
Columns[i].SortingIcon.Style = null;
|
||||||
|
if (Columns[i].SortingIcon.Source != null)
|
||||||
|
Columns[i].SortingIcon.Source = null;
|
||||||
|
_sortingOrders[i] = SortingOrder.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_internalItems = items;
|
||||||
|
|
||||||
|
_sortingOrders[sData.Index] = order;
|
||||||
|
SortedColumnIndex = sData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private View GetHeaderViewForColumn(DataGridColumn column)
|
||||||
|
{
|
||||||
|
column.HeaderLabel.Style = column.HeaderLabelStyle ?? this.HeaderLabelStyle ?? (Style)_headerView.Resources["HeaderDefaultStyle"];
|
||||||
|
|
||||||
|
Grid grid = new Grid
|
||||||
|
{
|
||||||
|
ColumnSpacing = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||||
|
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
|
||||||
|
|
||||||
|
if (IsSortable)
|
||||||
|
{
|
||||||
|
column.SortingIcon.Style = (Style)_headerView.Resources["ImageStyleBase"];
|
||||||
|
|
||||||
|
grid.Children.Add(column.SortingIcon);
|
||||||
|
Grid.SetColumn(column.SortingIcon, 1);
|
||||||
|
|
||||||
|
TapGestureRecognizer tgr = new TapGestureRecognizer();
|
||||||
|
tgr.Tapped += (s, e) =>
|
||||||
|
{
|
||||||
|
int index = Columns.IndexOf(column);
|
||||||
|
SortingOrder order = _sortingOrders[index] == SortingOrder.Ascendant ? SortingOrder.Descendant : SortingOrder.Ascendant;
|
||||||
|
|
||||||
|
if (Columns.ElementAt(index).SortingEnabled)
|
||||||
|
SortedColumnIndex = new SortData(index, order);
|
||||||
|
};
|
||||||
|
grid.GestureRecognizers.Add(tgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
grid.Children.Add(column.HeaderLabel);
|
||||||
|
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitHeaderView()
|
||||||
|
{
|
||||||
|
SetColumnsBindingContext();
|
||||||
|
_headerView.Children.Clear();
|
||||||
|
_headerView.ColumnDefinitions.Clear();
|
||||||
|
_sortingOrders.Clear();
|
||||||
|
|
||||||
|
_headerView.Padding = new Thickness(BorderThickness.Left, BorderThickness.Top, BorderThickness.Right, 0);
|
||||||
|
_headerView.ColumnSpacing = BorderThickness.HorizontalThickness / 2;
|
||||||
|
|
||||||
|
if (Columns != null)
|
||||||
|
{
|
||||||
|
foreach (var col in Columns)
|
||||||
|
{
|
||||||
|
_headerView.ColumnDefinitions.Add(new ColumnDefinition { Width = col.Width });
|
||||||
|
|
||||||
|
var cell = GetHeaderViewForColumn(col);
|
||||||
|
|
||||||
|
_headerView.Children.Add(cell);
|
||||||
|
Grid.SetColumn(cell, Columns.IndexOf(col));
|
||||||
|
|
||||||
|
_sortingOrders.Add(Columns.IndexOf(col), SortingOrder.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetColumnsBindingContext()
|
||||||
|
{
|
||||||
|
if (Columns != null)
|
||||||
|
foreach (var c in Columns)
|
||||||
|
c.BindingContext = BindingContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Private Methods
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
using System;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public class DataGridColumn : BindableObject, IDefinition
|
||||||
|
{
|
||||||
|
#region bindable properties
|
||||||
|
public static readonly BindableProperty WidthProperty =
|
||||||
|
BindableProperty.Create(nameof(Width), typeof(GridLength), typeof(DataGridColumn), new GridLength(1, GridUnitType.Star),
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
if (oldValue != newValue)
|
||||||
|
{
|
||||||
|
(bindable as DataGridColumn).OnSizeChanged();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty TitleProperty =
|
||||||
|
BindableProperty.Create(nameof(Title), typeof(string), typeof(DataGridColumn), string.Empty,
|
||||||
|
propertyChanged: (b, o, n) => (b as DataGridColumn).HeaderLabel.Text = (string)n);
|
||||||
|
|
||||||
|
public static readonly BindableProperty FormattedTitleProperty =
|
||||||
|
BindableProperty.Create(nameof(FormattedTitle), typeof(FormattedString), typeof(DataGridColumn),
|
||||||
|
propertyChanged: (b, o, n) => (b as DataGridColumn).HeaderLabel.FormattedText = (FormattedString)n);
|
||||||
|
|
||||||
|
public static readonly BindableProperty PropertyNameProperty =
|
||||||
|
BindableProperty.Create(nameof(PropertyName), typeof(string), typeof(DataGridColumn), null);
|
||||||
|
|
||||||
|
public static readonly BindableProperty StringFormatProperty =
|
||||||
|
BindableProperty.Create(nameof(StringFormat), typeof(string), typeof(DataGridColumn), null);
|
||||||
|
|
||||||
|
public static readonly BindableProperty CellTemplateProperty =
|
||||||
|
BindableProperty.Create(nameof(CellTemplate), typeof(DataTemplate), typeof(DataGridColumn), null);
|
||||||
|
|
||||||
|
public static readonly BindableProperty HorizontalContentAlignmentProperty =
|
||||||
|
BindableProperty.Create(nameof(HorizontalContentAlignment), typeof(LayoutOptions), typeof(DataGridColumn), LayoutOptions.Center);
|
||||||
|
|
||||||
|
public static readonly BindableProperty VerticalContentAlignmentProperty =
|
||||||
|
BindableProperty.Create(nameof(VerticalContentAlignment), typeof(LayoutOptions), typeof(DataGridColumn), LayoutOptions.Center);
|
||||||
|
|
||||||
|
public static readonly BindableProperty SortingEnabledProperty =
|
||||||
|
BindableProperty.Create(nameof(SortingEnabled), typeof(bool), typeof(DataGridColumn), true);
|
||||||
|
|
||||||
|
public static readonly BindableProperty HeaderLabelStyleProperty =
|
||||||
|
BindableProperty.Create(nameof(HeaderLabelStyle), typeof(Style), typeof(DataGridColumn),
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
if ((b as DataGridColumn).HeaderLabel != null && (o != n))
|
||||||
|
(b as DataGridColumn).HeaderLabel.Style = n as Style;
|
||||||
|
});
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region properties
|
||||||
|
|
||||||
|
public GridLength Width
|
||||||
|
{
|
||||||
|
get { return (GridLength)GetValue(WidthProperty); }
|
||||||
|
set { SetValue(WidthProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(TitleProperty); }
|
||||||
|
set { SetValue(TitleProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public FormattedString FormattedTitle
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(FormattedTitleProperty); }
|
||||||
|
set { SetValue(FormattedTitleProperty, value); }
|
||||||
|
}
|
||||||
|
public string PropertyName
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(PropertyNameProperty); }
|
||||||
|
set { SetValue(PropertyNameProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StringFormat
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(StringFormatProperty); }
|
||||||
|
set { SetValue(StringFormatProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataTemplate CellTemplate
|
||||||
|
{
|
||||||
|
get { return (DataTemplate)GetValue(CellTemplateProperty); }
|
||||||
|
set { SetValue(CellTemplateProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Image SortingIcon { get; set; }
|
||||||
|
internal Label HeaderLabel { get; set; }
|
||||||
|
|
||||||
|
public LayoutOptions HorizontalContentAlignment
|
||||||
|
{
|
||||||
|
get { return (LayoutOptions)GetValue(HorizontalContentAlignmentProperty); }
|
||||||
|
set { SetValue(HorizontalContentAlignmentProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayoutOptions VerticalContentAlignment
|
||||||
|
{
|
||||||
|
get { return (LayoutOptions)GetValue(VerticalContentAlignmentProperty); }
|
||||||
|
set { SetValue(VerticalContentAlignmentProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SortingEnabled
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(SortingEnabledProperty); }
|
||||||
|
set { SetValue(SortingEnabledProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Style HeaderLabelStyle
|
||||||
|
{
|
||||||
|
get { return (Style)GetValue(HeaderLabelStyleProperty); }
|
||||||
|
set { SetValue(HeaderLabelStyleProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public event EventHandler SizeChanged;
|
||||||
|
|
||||||
|
public DataGridColumn()
|
||||||
|
{
|
||||||
|
HeaderLabel = new Label();
|
||||||
|
SortingIcon = new Image();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnSizeChanged()
|
||||||
|
{
|
||||||
|
SizeChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using Xamarin.Forms;
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
internal class DataGridRowTemplateSelector : DataTemplateSelector
|
||||||
|
{
|
||||||
|
private static DataTemplate _dataGridRowTemplate;
|
||||||
|
|
||||||
|
public DataGridRowTemplateSelector()
|
||||||
|
{
|
||||||
|
_dataGridRowTemplate = new DataTemplate(typeof(DataGridViewCell));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
|
||||||
|
{
|
||||||
|
ListView listView = container as ListView;
|
||||||
|
DataGrid dataGrid = listView.Parent as DataGrid;
|
||||||
|
var items = dataGrid.InternalItems;
|
||||||
|
|
||||||
|
_dataGridRowTemplate.SetValue(DataGridViewCell.DataGridProperty, dataGrid);
|
||||||
|
_dataGridRowTemplate.SetValue(DataGridViewCell.RowContextProperty, item);
|
||||||
|
|
||||||
|
if (items != null)
|
||||||
|
{
|
||||||
|
_dataGridRowTemplate.SetValue(DataGridViewCell.IndexProperty, items.IndexOf(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _dataGridRowTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
using Xamarin.Forms;
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
internal sealed class DataGridViewCell : ViewCell
|
||||||
|
{
|
||||||
|
#region Fields
|
||||||
|
Grid _mainLayout;
|
||||||
|
Color _bgColor;
|
||||||
|
Color _textColor;
|
||||||
|
bool _hasSelected;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region properties
|
||||||
|
public DataGrid DataGrid
|
||||||
|
{
|
||||||
|
get { return (DataGrid)GetValue(DataGridProperty); }
|
||||||
|
set { SetValue(DataGridProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Index
|
||||||
|
{
|
||||||
|
get { return (int)GetValue(IndexProperty); }
|
||||||
|
set { SetValue(IndexProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public object RowContext
|
||||||
|
{
|
||||||
|
get { return GetValue(RowContextProperty); }
|
||||||
|
set { SetValue(RowContextProperty, value); }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Bindable Properties
|
||||||
|
public static readonly BindableProperty DataGridProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(DataGrid),
|
||||||
|
typeof(DataGrid),
|
||||||
|
typeof(DataGridViewCell),
|
||||||
|
null,
|
||||||
|
propertyChanged: (b, o, n) => (b as DataGridViewCell).CreateView());
|
||||||
|
|
||||||
|
public static readonly BindableProperty IndexProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(Index),
|
||||||
|
typeof(int),
|
||||||
|
typeof(DataGridViewCell),
|
||||||
|
0,
|
||||||
|
propertyChanged: (b, o, n) => (b as DataGridViewCell).UpdateBackgroundColor());
|
||||||
|
|
||||||
|
public static readonly BindableProperty RowContextProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
nameof(RowContext),
|
||||||
|
typeof(object),
|
||||||
|
typeof(DataGridViewCell),
|
||||||
|
propertyChanged: (b, o, n) => (b as DataGridViewCell).UpdateBackgroundColor());
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
private void CreateView()
|
||||||
|
{
|
||||||
|
UpdateBackgroundColor();
|
||||||
|
|
||||||
|
_mainLayout = new Grid()
|
||||||
|
{
|
||||||
|
BackgroundColor = DataGrid.BorderColor,
|
||||||
|
RowSpacing = 0,
|
||||||
|
ColumnSpacing = DataGrid.BorderThickness.HorizontalThickness / 2,
|
||||||
|
Padding = new Thickness(DataGrid.BorderThickness.HorizontalThickness / 2,
|
||||||
|
DataGrid.BorderThickness.VerticalThickness / 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var col in DataGrid.Columns)
|
||||||
|
{
|
||||||
|
_mainLayout.ColumnDefinitions.Add(new ColumnDefinition() { Width = col.Width });
|
||||||
|
View cell;
|
||||||
|
|
||||||
|
if (col.CellTemplate != null)
|
||||||
|
{
|
||||||
|
cell = new ContentView() { Content = col.CellTemplate.CreateContent() as View };
|
||||||
|
if (col.PropertyName != null)
|
||||||
|
{
|
||||||
|
cell.SetBinding(BindingContextProperty,
|
||||||
|
new Binding(col.PropertyName, source: RowContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var text = new Label
|
||||||
|
{
|
||||||
|
TextColor = _textColor,
|
||||||
|
HorizontalOptions = col.HorizontalContentAlignment,
|
||||||
|
VerticalOptions = col.VerticalContentAlignment,
|
||||||
|
LineBreakMode = LineBreakMode.WordWrap,
|
||||||
|
};
|
||||||
|
text.SetBinding(Label.TextProperty, new Binding(col.PropertyName, BindingMode.Default, stringFormat: col.StringFormat));
|
||||||
|
text.SetBinding(Label.FontSizeProperty, new Binding(DataGrid.FontSizeProperty.PropertyName, BindingMode.Default, source: DataGrid));
|
||||||
|
text.SetBinding(Label.FontFamilyProperty, new Binding(DataGrid.FontFamilyProperty.PropertyName, BindingMode.Default, source: DataGrid));
|
||||||
|
|
||||||
|
cell = new ContentView
|
||||||
|
{
|
||||||
|
Padding = 0,
|
||||||
|
BackgroundColor = _bgColor,
|
||||||
|
Content = text,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_mainLayout.Children.Add(cell);
|
||||||
|
Grid.SetColumn(cell, DataGrid.Columns.IndexOf(col));
|
||||||
|
}
|
||||||
|
|
||||||
|
View = _mainLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateBackgroundColor()
|
||||||
|
{
|
||||||
|
_hasSelected = DataGrid.SelectedItem == RowContext;
|
||||||
|
int actualIndex = DataGrid?.InternalItems?.IndexOf(BindingContext) ?? -1;
|
||||||
|
if (actualIndex > -1)
|
||||||
|
{
|
||||||
|
_bgColor = (DataGrid.SelectionEnabled && DataGrid.SelectedItem != null && DataGrid.SelectedItem == RowContext) ?
|
||||||
|
DataGrid.ActiveRowColor : DataGrid.RowsBackgroundColorPalette.GetColor(Index, BindingContext);
|
||||||
|
_textColor = DataGrid.RowsTextColorPalette.GetColor(actualIndex, BindingContext);
|
||||||
|
|
||||||
|
ChangeColor(_bgColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChangeColor(Color color)
|
||||||
|
{
|
||||||
|
foreach (var v in _mainLayout.Children)
|
||||||
|
{
|
||||||
|
v.BackgroundColor = color;
|
||||||
|
var contentView = v as ContentView;
|
||||||
|
if (contentView?.Content is Label)
|
||||||
|
((Label)contentView.Content).TextColor = _textColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnBindingContextChanged()
|
||||||
|
{
|
||||||
|
base.OnBindingContextChanged();
|
||||||
|
UpdateBackgroundColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnParentSet()
|
||||||
|
{
|
||||||
|
base.OnParentSet();
|
||||||
|
if (Parent != null)
|
||||||
|
DataGrid.ItemSelected += DataGrid_ItemSelected;
|
||||||
|
else
|
||||||
|
DataGrid.ItemSelected -= DataGrid_ItemSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DataGrid_ItemSelected(object sender, SelectedItemChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataGrid.SelectionEnabled && (e.SelectedItem == RowContext || _hasSelected))
|
||||||
|
{
|
||||||
|
UpdateBackgroundColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using Xamarin.Forms;
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public interface IColorProvider
|
||||||
|
{
|
||||||
|
Color GetColor(int rowIndex, object item);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public sealed class PaletteCollection : List<Color>, IColorProvider
|
||||||
|
{
|
||||||
|
public Color GetColor(int rowIndex, object item)
|
||||||
|
{
|
||||||
|
if (Count > 0)
|
||||||
|
return this.ElementAt(rowIndex % Count);
|
||||||
|
else
|
||||||
|
return default(Color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
|
||||||
|
[TypeConverter(typeof(SortDataTypeConverter))]
|
||||||
|
public class SortData
|
||||||
|
{
|
||||||
|
|
||||||
|
#region ctor
|
||||||
|
public SortData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortData(int index, SortingOrder order)
|
||||||
|
{
|
||||||
|
Index = index;
|
||||||
|
Order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public SortingOrder Order { get; set; }
|
||||||
|
|
||||||
|
public int Index { get; set; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public static implicit operator SortData(int index)
|
||||||
|
{
|
||||||
|
return new SortData
|
||||||
|
{
|
||||||
|
Index = Math.Abs(index),
|
||||||
|
Order = index < 0 ? SortingOrder.Descendant : SortingOrder.Ascendant
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is SortData)
|
||||||
|
{
|
||||||
|
SortData other = obj as SortData;
|
||||||
|
return other.Index == Index && other.Order == Order;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public class SortDataTypeConverter : TypeConverter
|
||||||
|
{
|
||||||
|
|
||||||
|
public override bool CanConvertFrom(Type sourceType)
|
||||||
|
{
|
||||||
|
return base.CanConvertFrom(sourceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ConvertFromInvariantString(string value)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
if (int.TryParse(value, out index))
|
||||||
|
return (SortData)index;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public enum SortingOrder
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Ascendant = 1,
|
||||||
|
Descendant = 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ContentView
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
x:Class="Aurora.Design.Components.Dialogs.Modal">
|
||||||
|
<ContentView.Content>
|
||||||
|
<ContentPresenter
|
||||||
|
x:Name="ViewContent"/>
|
||||||
|
</ContentView.Content>
|
||||||
|
</ContentView>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.Dialogs
|
||||||
|
{
|
||||||
|
public partial class Modal : ContentView
|
||||||
|
{
|
||||||
|
public Modal()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+208
@@ -0,0 +1,208 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.HorizontalList
|
||||||
|
{
|
||||||
|
public class HorizontalList : Grid
|
||||||
|
{
|
||||||
|
private ICommand _innerSelectedCommand;
|
||||||
|
private readonly ScrollView _scrollView;
|
||||||
|
private readonly StackLayout _itemsStackLayout;
|
||||||
|
|
||||||
|
public event EventHandler SelectedItemChanged;
|
||||||
|
private NotifyCollectionChangedEventHandler _itemsChangedHandler;
|
||||||
|
|
||||||
|
public StackOrientation ListOrientation { get; set; }
|
||||||
|
|
||||||
|
public double Spacing { get; set; }
|
||||||
|
|
||||||
|
public static readonly BindableProperty SelectedCommandProperty =
|
||||||
|
BindableProperty.Create("SelectedCommand", typeof(ICommand), typeof(HorizontalList), null);
|
||||||
|
|
||||||
|
public static readonly BindableProperty ItemsSourceProperty =
|
||||||
|
BindableProperty.Create("ItemsSource",
|
||||||
|
returnType: typeof(ObservableCollection<object>),
|
||||||
|
declaringType: typeof(HorizontalList),
|
||||||
|
defaultValue: default(ObservableCollection<object>),
|
||||||
|
defaultBindingMode: BindingMode.TwoWay,
|
||||||
|
propertyChanged: ItemsSourceChanged);
|
||||||
|
|
||||||
|
public static readonly BindableProperty SelectedItemProperty =
|
||||||
|
BindableProperty.Create("SelectedItem", typeof(object), typeof(HorizontalList), null, BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged);
|
||||||
|
|
||||||
|
public static readonly BindableProperty ItemTemplateProperty =
|
||||||
|
BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(HorizontalList), default(DataTemplate));
|
||||||
|
|
||||||
|
public ICommand SelectedCommand
|
||||||
|
{
|
||||||
|
get { return (ICommand)GetValue(SelectedCommandProperty); }
|
||||||
|
set { SetValue(SelectedCommandProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<object> ItemsSource
|
||||||
|
{
|
||||||
|
get { return (ObservableCollection<object>)GetValue(ItemsSourceProperty); }
|
||||||
|
set { SetValue(ItemsSourceProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public object SelectedItem
|
||||||
|
{
|
||||||
|
get { return (object)GetValue(SelectedItemProperty); }
|
||||||
|
set { SetValue(SelectedItemProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataTemplate ItemTemplate
|
||||||
|
{
|
||||||
|
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
|
||||||
|
set { SetValue(ItemTemplateProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
|
{
|
||||||
|
HorizontalList itemsLayout = bindable as HorizontalList;
|
||||||
|
itemsLayout.SetItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HorizontalList()
|
||||||
|
{
|
||||||
|
_itemsChangedHandler = OnItemsChanged;
|
||||||
|
// BackgroundColor = Color.FromHex("#1E2634");
|
||||||
|
Spacing = 6;
|
||||||
|
_scrollView = new ScrollView();
|
||||||
|
_itemsStackLayout = new StackLayout
|
||||||
|
{
|
||||||
|
Padding = Padding,
|
||||||
|
Spacing = Spacing,
|
||||||
|
HorizontalOptions = LayoutOptions.FillAndExpand
|
||||||
|
};
|
||||||
|
|
||||||
|
_scrollView.Content = _itemsStackLayout;
|
||||||
|
Children.Add(_scrollView);
|
||||||
|
}
|
||||||
|
|
||||||
|
~HorizontalList()
|
||||||
|
{
|
||||||
|
ItemsSource.CollectionChanged -= _itemsChangedHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void SetItems()
|
||||||
|
{
|
||||||
|
_itemsStackLayout.Children.Clear();
|
||||||
|
_itemsStackLayout.Spacing = Spacing;
|
||||||
|
|
||||||
|
_innerSelectedCommand = new Command<View>(view =>
|
||||||
|
{
|
||||||
|
SelectedItem = view.BindingContext;
|
||||||
|
SelectedItem = null; // Allowing item second time selection
|
||||||
|
});
|
||||||
|
|
||||||
|
_itemsStackLayout.Orientation = ListOrientation;
|
||||||
|
_scrollView.Orientation = ListOrientation == StackOrientation.Horizontal
|
||||||
|
? ScrollOrientation.Horizontal
|
||||||
|
: ScrollOrientation.Vertical;
|
||||||
|
|
||||||
|
if (ItemsSource == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup collection events
|
||||||
|
ItemsSource.CollectionChanged += _itemsChangedHandler;
|
||||||
|
|
||||||
|
foreach (var item in ItemsSource)
|
||||||
|
{
|
||||||
|
_itemsStackLayout.Children.Add(GetItemView(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual View GetItemView(object item)
|
||||||
|
{
|
||||||
|
var content = ItemTemplate.CreateContent();
|
||||||
|
var view = content as View;
|
||||||
|
|
||||||
|
if (view == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
view.BindingContext = item;
|
||||||
|
|
||||||
|
var gesture = new TapGestureRecognizer
|
||||||
|
{
|
||||||
|
Command = _innerSelectedCommand,
|
||||||
|
CommandParameter = view
|
||||||
|
};
|
||||||
|
|
||||||
|
AddGesture(view, gesture);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddGesture(View view, TapGestureRecognizer gesture)
|
||||||
|
{
|
||||||
|
view.GestureRecognizers.Add(gesture);
|
||||||
|
|
||||||
|
var layout = view as Layout<View>;
|
||||||
|
|
||||||
|
if (layout == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var child in layout.Children)
|
||||||
|
{
|
||||||
|
AddGesture(child, gesture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
|
{
|
||||||
|
var itemsView = (HorizontalList)bindable;
|
||||||
|
|
||||||
|
if (newValue == oldValue && newValue != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsView.SelectedItemChanged?.Invoke(itemsView, EventArgs.Empty);
|
||||||
|
|
||||||
|
if (itemsView.SelectedCommand?.CanExecute(newValue) ?? false)
|
||||||
|
{
|
||||||
|
itemsView.SelectedCommand?.Execute(newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
switch (e.Action)
|
||||||
|
{
|
||||||
|
case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
|
||||||
|
{
|
||||||
|
foreach (object item in e.NewItems)
|
||||||
|
{
|
||||||
|
_itemsStackLayout.Children.Add(GetItemView(item));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
|
||||||
|
{
|
||||||
|
foreach (object item in e.OldItems)
|
||||||
|
{
|
||||||
|
//Clear layout and rebuild
|
||||||
|
_itemsStackLayout.Children.Clear();
|
||||||
|
foreach (var source in ItemsSource)
|
||||||
|
{
|
||||||
|
_itemsStackLayout.Children.Add(GetItemView(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Aurora.Design.Components.ImageButton.ImageButton">
|
||||||
|
<ContentView.GestureRecognizers>
|
||||||
|
<TapGestureRecognizer Tapped="OnButtonTapped" />
|
||||||
|
</ContentView.GestureRecognizers>
|
||||||
|
<ContentView.Content>
|
||||||
|
<StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
|
||||||
|
<Image x:Name="imgButton" Aspect="AspectFit" />
|
||||||
|
</StackLayout>
|
||||||
|
</ContentView.Content>
|
||||||
|
</ContentView>
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.ImageButton
|
||||||
|
{
|
||||||
|
public partial class ImageButton : ContentView
|
||||||
|
{
|
||||||
|
public ImageButton()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly BindableProperty SourceProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
"Source",
|
||||||
|
typeof(ImageSource),
|
||||||
|
typeof(ImageButton),
|
||||||
|
null,
|
||||||
|
BindingMode.TwoWay,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
ImageButton control = (ImageButton)bindable;
|
||||||
|
|
||||||
|
control.imgButton.Source = (ImageSource)newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty CommandProperty = BindableProperty.Create(
|
||||||
|
"Command",
|
||||||
|
typeof(Command),
|
||||||
|
typeof(ImageButton),
|
||||||
|
null,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
ImageButton control = (ImageButton)bindable;
|
||||||
|
var command = (Command)newValue;
|
||||||
|
|
||||||
|
CanExecute(command, control);
|
||||||
|
|
||||||
|
command.CanExecuteChanged += (sender, e) =>
|
||||||
|
{
|
||||||
|
CanExecute(sender, control);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(
|
||||||
|
"CommandParameter",
|
||||||
|
typeof(object),
|
||||||
|
typeof(ImageButton),
|
||||||
|
null);
|
||||||
|
|
||||||
|
private static void CanExecute(object sender, ImageButton control)
|
||||||
|
{
|
||||||
|
var cmd = (Command)sender;
|
||||||
|
control.imgButton.IsEnabled = cmd.CanExecute(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageSource Source
|
||||||
|
{
|
||||||
|
get { return (ImageSource)GetValue(SourceProperty); }
|
||||||
|
set { SetValue(SourceProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public event EventHandler<EventArgs> Tapped;
|
||||||
|
|
||||||
|
public Command Command
|
||||||
|
{
|
||||||
|
get { return (Command)GetValue(CommandProperty); }
|
||||||
|
set { SetValue(CommandProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public object CommandParameter
|
||||||
|
{
|
||||||
|
get { return GetValue(CommandParameterProperty); }
|
||||||
|
set { SetValue(CommandParameterProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnButtonTapped(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
object resolvedParameter;
|
||||||
|
|
||||||
|
if (CommandParameter != null)
|
||||||
|
{
|
||||||
|
resolvedParameter = CommandParameter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resolvedParameter = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Command?.CanExecute(resolvedParameter) ?? true)
|
||||||
|
{
|
||||||
|
this.AbortAnimation("imgButtonAnim");
|
||||||
|
new Animation(v => imgButton.Scale = v, 1, 0.5).Commit(imgButton, "imgButtonAnim", 16, 150, Easing.SinOut,
|
||||||
|
(v, c) =>
|
||||||
|
{
|
||||||
|
imgButton.Scale = 1;
|
||||||
|
Tapped?.Invoke(this, args);
|
||||||
|
Command?.Execute(resolvedParameter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Label {
|
||||||
|
margin-left: 25;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: middle;
|
||||||
|
word-wrap: break-word;
|
||||||
|
font-size: 14;
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ContentView
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:dg="clr-namespace:Aurora.Design.Components.DataGrid"
|
||||||
|
x:Class="Aurora.Design.Components.Library.Library">
|
||||||
|
<ContentView.Resources>
|
||||||
|
<StyleSheet
|
||||||
|
Source="Library.css"/>
|
||||||
|
</ContentView.Resources>
|
||||||
|
<ContentView.Content>
|
||||||
|
<dg:DataGrid
|
||||||
|
x:Name="LibraryDataGrid"
|
||||||
|
SelectionEnabled="True"
|
||||||
|
RowHeight="30"
|
||||||
|
BorderColor="#181818"
|
||||||
|
BorderThickness="0"
|
||||||
|
HeaderHeight="45"
|
||||||
|
HeaderBackground="#181818">
|
||||||
|
<dg:DataGrid.HeaderLabelStyle>
|
||||||
|
<Style
|
||||||
|
TargetType="Label">
|
||||||
|
<Setter
|
||||||
|
Property="HorizontalOptions"
|
||||||
|
Value="Start"/>
|
||||||
|
<Setter
|
||||||
|
Property="FontSize"
|
||||||
|
Value="14"/>
|
||||||
|
<Setter
|
||||||
|
Property="TextColor"
|
||||||
|
Value="White"/>
|
||||||
|
</Style>
|
||||||
|
</dg:DataGrid.HeaderLabelStyle>
|
||||||
|
<dg:DataGrid.GestureRecognizers>
|
||||||
|
<TapGestureRecognizer
|
||||||
|
NumberOfTapsRequired="2"/>
|
||||||
|
</dg:DataGrid.GestureRecognizers>
|
||||||
|
<dg:DataGrid.Columns>
|
||||||
|
<dg:DataGridColumn
|
||||||
|
Title=""
|
||||||
|
PropertyName="Icon"
|
||||||
|
Width="15">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Image
|
||||||
|
Source="../../Resources/unselected.png"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
<dg:DataGridColumn
|
||||||
|
Title="Title"
|
||||||
|
PropertyName="Metadata.Title"
|
||||||
|
Width="2*">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Text="{Binding .}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
<dg:DataGridColumn
|
||||||
|
Title="Album"
|
||||||
|
PropertyName="Metadata.Album"
|
||||||
|
Width="0.95*">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Text="{Binding .}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
<dg:DataGridColumn
|
||||||
|
Title="Artist"
|
||||||
|
PropertyName="Metadata.Artist"
|
||||||
|
Width="1*">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Text="{Binding .}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
</dg:DataGrid.Columns>
|
||||||
|
<dg:DataGrid.RowsTextColorPalette>
|
||||||
|
<dg:PaletteCollection>
|
||||||
|
<Color>White</Color>
|
||||||
|
</dg:PaletteCollection>
|
||||||
|
</dg:DataGrid.RowsTextColorPalette>
|
||||||
|
<dg:DataGrid.RowsBackgroundColorPalette>
|
||||||
|
<dg:PaletteCollection>
|
||||||
|
<Color>Transparent</Color>
|
||||||
|
</dg:PaletteCollection>
|
||||||
|
</dg:DataGrid.RowsBackgroundColorPalette>
|
||||||
|
</dg:DataGrid>
|
||||||
|
</ContentView.Content>
|
||||||
|
</ContentView>
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.Library
|
||||||
|
{
|
||||||
|
public partial class Library : ContentView
|
||||||
|
{
|
||||||
|
public Library()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
this.LibraryDataGrid.ItemSelected += (sender, e) =>
|
||||||
|
{
|
||||||
|
this.SelectedItem = e.SelectedItem;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ItemsSource Property
|
||||||
|
/// <summary>
|
||||||
|
/// Bindable Property for the ItemsSource of the datagrid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""ItemsSource""></param>
|
||||||
|
/// <param name="typeof(IEnumerable<object>"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static readonly BindableProperty ItemsSourceProperty =
|
||||||
|
BindableProperty.Create(propertyName: "ItemsSource",
|
||||||
|
returnType: typeof(IEnumerable<object>),
|
||||||
|
declaringType: typeof(Library),
|
||||||
|
defaultBindingMode: BindingMode.Default,
|
||||||
|
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
|
||||||
|
{
|
||||||
|
Library control = bindable as Library;
|
||||||
|
control.LibraryDataGrid.ItemsSource = (IEnumerable<object>)newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Backing property for the ItemsSource property.
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public IEnumerable<object> ItemsSource
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (IEnumerable<object>)GetValue(ItemsSourceProperty);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(ItemsSourceProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion ItemsSource Property
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bindable property for the selected item field on the datagrid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""SelectedItem""></param>
|
||||||
|
/// <param name="typeof(BaseMetadata"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static readonly BindableProperty SelectedItemProperty =
|
||||||
|
BindableProperty.Create(propertyName: "SelectedItem",
|
||||||
|
returnType: typeof(object),
|
||||||
|
declaringType: typeof(Library),
|
||||||
|
defaultBindingMode: BindingMode.TwoWay);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Backing property for the SelectedItem property.
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public object SelectedItem
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ((object)GetValue(SelectedItemProperty));
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(SelectedItemProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bindable property for the item double clicked command
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""SelectedItem""></param>
|
||||||
|
/// <param name="typeof(BaseMetadata"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static readonly BindableProperty ItemDoubleClickedProperty =
|
||||||
|
BindableProperty.Create(propertyName: "ItemDoubleClicked",
|
||||||
|
returnType: typeof(Command),
|
||||||
|
declaringType: typeof(Library),
|
||||||
|
propertyChanged: OnDoubleClickPropertyChanged);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Public backing property
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public Command ItemDoubleClicked
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (Command)GetValue(ItemDoubleClickedProperty);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(ItemDoubleClickedProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event handler for double click property. Adds command execute handler.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bindable"></param>
|
||||||
|
/// <param name="newValue"></param>
|
||||||
|
/// <param name="oldValue"></param>
|
||||||
|
private static void OnDoubleClickPropertyChanged(BindableObject bindable, object newValue, object oldValue)
|
||||||
|
{
|
||||||
|
Library control = bindable as Library;
|
||||||
|
var dataGrid = control.LibraryDataGrid;
|
||||||
|
if (dataGrid.GestureRecognizers.Count > 0)
|
||||||
|
{
|
||||||
|
var gestureRecognizer = dataGrid.GestureRecognizers.First();
|
||||||
|
|
||||||
|
if (gestureRecognizer is TapGestureRecognizer)
|
||||||
|
{
|
||||||
|
TapGestureRecognizer tap = gestureRecognizer as TapGestureRecognizer;
|
||||||
|
tap.Tapped += (sender, e) =>
|
||||||
|
{
|
||||||
|
control.ItemDoubleClicked.Execute(null);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#PlayerControlContainer {
|
||||||
|
background-color: #303030;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
color: white;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: middle;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#MediaInfoContainer {
|
||||||
|
width: 150;
|
||||||
|
margin-top: 10;
|
||||||
|
margin-bottom: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
#MediaInfoContainer label {
|
||||||
|
margin-left: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
#AlbumArtBoxView {
|
||||||
|
background-color: black;
|
||||||
|
width: 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PlayButton {
|
||||||
|
width: 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DirectionButton {
|
||||||
|
width: 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
.LibraryButton {
|
||||||
|
width: 25;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
margin-top: 10;
|
||||||
|
margin-left: 15;
|
||||||
|
margin-right: 15;
|
||||||
|
margin-bottom: 10;
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ContentView
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:imgBtn="clr-namespace:Aurora.Design.Components.ImageButton"
|
||||||
|
x:Class="Aurora.Design.Components.MediaPlayer.Player">
|
||||||
|
<ContentView.Resources>
|
||||||
|
<StyleSheet
|
||||||
|
Source="Player.css"/>
|
||||||
|
</ContentView.Resources>
|
||||||
|
<ContentView.Content>
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition
|
||||||
|
Width="200"/>
|
||||||
|
<ColumnDefinition
|
||||||
|
Width="*"/>
|
||||||
|
<ColumnDefinition
|
||||||
|
Width="100"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<StackLayout
|
||||||
|
Grid.Column="0"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
<BoxView
|
||||||
|
x:Name="AlbumArtBoxView"/>
|
||||||
|
<StackLayout
|
||||||
|
x:Name="MediaInfoContainer"
|
||||||
|
HorizontalOptions="StartAndExpand">
|
||||||
|
<Label
|
||||||
|
x:Name="SongTitleLabel"
|
||||||
|
LineBreakMode="TailTruncation"/>
|
||||||
|
<Label
|
||||||
|
x:Name="ArtistNameLabel"
|
||||||
|
LineBreakMode="TailTruncation"/>
|
||||||
|
</StackLayout>
|
||||||
|
</StackLayout>
|
||||||
|
<StackLayout
|
||||||
|
x:Name="PlayerControlContainer"
|
||||||
|
Grid.Column="1"
|
||||||
|
HorizontalOptions="Center"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
<imgBtn:ImageButton
|
||||||
|
x:Name="ShuffleButton"
|
||||||
|
StyleClass="LibraryButton"
|
||||||
|
Source="Resources/shuffle.png"/>
|
||||||
|
<imgBtn:ImageButton
|
||||||
|
x:Name="PreviousButton"
|
||||||
|
StyleClass="DirectionButton"
|
||||||
|
Source="Resources/backward.png"/>
|
||||||
|
<imgBtn:ImageButton
|
||||||
|
x:Name="PlayButton"
|
||||||
|
StyleClass="PlayButton"/>
|
||||||
|
<imgBtn:ImageButton
|
||||||
|
x:Name="NextButton"
|
||||||
|
StyleClass="DirectionButton"
|
||||||
|
Source="Resources/forwards.png"/>
|
||||||
|
<imgBtn:ImageButton
|
||||||
|
x:Name="LoopButton"
|
||||||
|
StyleClass="LibraryButton"
|
||||||
|
Source="Resources/loop.png"/>
|
||||||
|
</StackLayout>
|
||||||
|
</Grid>
|
||||||
|
</ContentView.Content>
|
||||||
|
</ContentView>
|
||||||
@@ -0,0 +1,303 @@
|
|||||||
|
using System;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.MediaPlayer
|
||||||
|
{
|
||||||
|
public partial class Player : ContentView
|
||||||
|
{
|
||||||
|
public Player()
|
||||||
|
{
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
PlayButton.Source = ImageSource.FromFile("Resources/play.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#region SongTitle Bindable
|
||||||
|
public static readonly BindableProperty SongTitleProperty =
|
||||||
|
BindableProperty.Create(propertyName: "SongTitle",
|
||||||
|
returnType: typeof(string),
|
||||||
|
declaringType: typeof(Player),
|
||||||
|
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
|
||||||
|
{
|
||||||
|
Player component = bindable as Player;
|
||||||
|
component.SongTitleLabel.Text = (string)newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
public string SongTitle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (string)GetValue(SongTitleProperty);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(SongTitleProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion SongTitle Bindable
|
||||||
|
|
||||||
|
#region ArtistName Bindable
|
||||||
|
public static readonly BindableProperty ArtistNameProperty =
|
||||||
|
BindableProperty.Create(propertyName: "ArtistName",
|
||||||
|
returnType: typeof(string),
|
||||||
|
declaringType: typeof(Player),
|
||||||
|
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
|
||||||
|
{
|
||||||
|
Player component = bindable as Player;
|
||||||
|
component.ArtistNameLabel.Text = (string)newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
public string ArtistName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (string)GetValue(ArtistNameProperty);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(ArtistNameProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion ArtistName Bindable
|
||||||
|
|
||||||
|
#region PreviousButton
|
||||||
|
public static readonly BindableProperty PreviousButtonCommandProperty =
|
||||||
|
BindableProperty.Create(propertyName: "PreviousButtonCommand",
|
||||||
|
returnType: typeof(Command),
|
||||||
|
propertyChanged: OnPreviousButtonPropertyChanged,
|
||||||
|
declaringType: typeof(Player));
|
||||||
|
|
||||||
|
public Command PreviousButtonCommand
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (Command)GetValue(PreviousButtonCommandProperty);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(PreviousButtonCommandProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPreviousButtonClicked(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
if (PreviousButtonCommand.CanExecute(null))
|
||||||
|
{
|
||||||
|
PreviousButtonCommand.Execute(null);
|
||||||
|
PreviousButtonCommand.ChangeCanExecute();
|
||||||
|
PlayButtonCommand.ChangeCanExecute();
|
||||||
|
NextButtonCommand.ChangeCanExecute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event handler to hook up can execute events on property changed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bindable"></param>
|
||||||
|
/// <param name="newValue"></param>
|
||||||
|
/// <param name="oldValue"></param>
|
||||||
|
private static void OnPreviousButtonPropertyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
|
{
|
||||||
|
Player component = bindable as Player;
|
||||||
|
if (newValue is Command)
|
||||||
|
{
|
||||||
|
Command cmd = newValue as Command;
|
||||||
|
component.PreviousButton.Tapped += component.OnPreviousButtonClicked;
|
||||||
|
cmd.CanExecuteChanged += (sender, e) => OnPreviousButtonCanExecuteChanged(sender, e, component, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldValue is Command && oldValue != null)
|
||||||
|
{
|
||||||
|
Command cmd = newValue as Command;
|
||||||
|
component.PreviousButton.Tapped -= component.OnPreviousButtonClicked;
|
||||||
|
cmd.CanExecuteChanged -= (sender, e) => OnPreviousButtonCanExecuteChanged(sender, e, component, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Can execute changed event handler
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="eventArgs"></param>
|
||||||
|
/// <param name="component"></param>
|
||||||
|
/// <param name="cmd"></param>
|
||||||
|
private static void OnPreviousButtonCanExecuteChanged(object sender,
|
||||||
|
EventArgs eventArgs,
|
||||||
|
Player component,
|
||||||
|
Command cmd)
|
||||||
|
{
|
||||||
|
component.NextButton.IsEnabled = cmd.CanExecute(null);
|
||||||
|
}
|
||||||
|
#endregion PreviousButton
|
||||||
|
|
||||||
|
#region PlayButton
|
||||||
|
public static readonly BindableProperty PlayButtonCommandProperty =
|
||||||
|
BindableProperty.Create(propertyName: "PlayButtonCommand",
|
||||||
|
returnType: typeof(Command),
|
||||||
|
propertyChanged: OnPlayButtonPropertyChanged,
|
||||||
|
declaringType: typeof(Player));
|
||||||
|
|
||||||
|
public Command PlayButtonCommand
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (Command)GetValue(PlayButtonCommandProperty);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(PlayButtonCommandProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayButtonClicked(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
if (PlayButtonCommand.CanExecute(null))
|
||||||
|
{
|
||||||
|
PlayButtonCommand.Execute(null);
|
||||||
|
PreviousButtonCommand.ChangeCanExecute();
|
||||||
|
PlayButtonCommand.ChangeCanExecute();
|
||||||
|
NextButtonCommand.ChangeCanExecute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event handler to hook up can execute events on property changed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bindable"></param>
|
||||||
|
/// <param name="newValue"></param>
|
||||||
|
/// <param name="oldValue"></param>
|
||||||
|
private static void OnPlayButtonPropertyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
|
{
|
||||||
|
Player component = bindable as Player;
|
||||||
|
if (newValue is Command)
|
||||||
|
{
|
||||||
|
Command cmd = newValue as Command;
|
||||||
|
component.PlayButton.Tapped += component.OnPlayButtonClicked;
|
||||||
|
cmd.CanExecuteChanged += (sender, e) => OnPlayButtonCanExecuteChanged(sender, e, component, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldValue is Command && oldValue != null)
|
||||||
|
{
|
||||||
|
Command cmd = newValue as Command;
|
||||||
|
component.PlayButton.Tapped -= component.OnPlayButtonClicked;
|
||||||
|
cmd.CanExecuteChanged -= (sender, e) => OnPlayButtonCanExecuteChanged(sender, e, component, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Can execute changed event handler
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="eventArgs"></param>
|
||||||
|
/// <param name="component"></param>
|
||||||
|
/// <param name="cmd"></param>
|
||||||
|
private static void OnPlayButtonCanExecuteChanged(object sender,
|
||||||
|
EventArgs eventArgs,
|
||||||
|
Player component,
|
||||||
|
Command cmd)
|
||||||
|
{
|
||||||
|
component.NextButton.IsEnabled = cmd.CanExecute(null);
|
||||||
|
}
|
||||||
|
#endregion PlayButton
|
||||||
|
|
||||||
|
#region NextButton
|
||||||
|
public static readonly BindableProperty NextButtonCommandProperty =
|
||||||
|
BindableProperty.Create(propertyName: "NextButtonCommand",
|
||||||
|
returnType: typeof(Command),
|
||||||
|
declaringType: typeof(Player),
|
||||||
|
propertyChanged: OnNextButtonPropertyChanged);
|
||||||
|
|
||||||
|
public Command NextButtonCommand
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (Command)GetValue(NextButtonCommandProperty);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(NextButtonCommandProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNextButtonClicked(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
if (NextButtonCommand.CanExecute(null))
|
||||||
|
{
|
||||||
|
NextButtonCommand.Execute(null);
|
||||||
|
PreviousButtonCommand.ChangeCanExecute();
|
||||||
|
PlayButtonCommand.ChangeCanExecute();
|
||||||
|
NextButtonCommand.ChangeCanExecute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event handler to hook up can execute events on property changed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bindable"></param>
|
||||||
|
/// <param name="newValue"></param>
|
||||||
|
/// <param name="oldValue"></param>
|
||||||
|
private static void OnNextButtonPropertyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
|
{
|
||||||
|
Player component = bindable as Player;
|
||||||
|
if (newValue is Command)
|
||||||
|
{
|
||||||
|
Command cmd = newValue as Command;
|
||||||
|
component.NextButton.Tapped += component.OnNextButtonClicked;
|
||||||
|
cmd.CanExecuteChanged += (sender, e) => OnNextButtonCanExecuteChanged(sender, e, component, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldValue is Command && oldValue != null)
|
||||||
|
{
|
||||||
|
Command cmd = oldValue as Command;
|
||||||
|
component.NextButton.Tapped -= component.OnNextButtonClicked;
|
||||||
|
cmd.CanExecuteChanged -= (sender, e) => OnNextButtonCanExecuteChanged(sender, e, component, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Can execute changed event handler
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="eventArgs"></param>
|
||||||
|
/// <param name="component"></param>
|
||||||
|
/// <param name="cmd"></param>
|
||||||
|
private static void OnNextButtonCanExecuteChanged(object sender,
|
||||||
|
EventArgs eventArgs,
|
||||||
|
Player component,
|
||||||
|
Command cmd)
|
||||||
|
{
|
||||||
|
|
||||||
|
component.NextButton.IsEnabled = cmd.CanExecute(null);
|
||||||
|
}
|
||||||
|
#endregion PlayButton
|
||||||
|
|
||||||
|
#region Playing Bindable
|
||||||
|
public static readonly BindableProperty IsPlayingProperty =
|
||||||
|
BindableProperty.Create(
|
||||||
|
propertyName: "IsPlaying",
|
||||||
|
returnType: typeof(bool),
|
||||||
|
declaringType: typeof(Player),
|
||||||
|
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
|
||||||
|
{
|
||||||
|
Player control = (Player)bindable;
|
||||||
|
if ((bool)newValue == true)
|
||||||
|
{
|
||||||
|
control.PlayButton.Source = ImageSource.FromFile("Resources/pause.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
control.PlayButton.Source = ImageSource.FromFile("Resources/play.png");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public bool IsPlaying
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(IsPlayingProperty); }
|
||||||
|
set { SetValue(IsPlayingProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Playing Binadable
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#MembersList {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
margin-left: 20;
|
||||||
|
margin-right: 20;
|
||||||
|
margin-top: 20;
|
||||||
|
margin-bottom: 20;
|
||||||
|
width: 150;
|
||||||
|
border-radius: 25;
|
||||||
|
background-color: #626363;
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid Label {
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
color: white;
|
||||||
|
font-size: 20;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ContentView
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
|
||||||
|
x:Class="Aurora.Design.Components.MemberList.MemberList">
|
||||||
|
<ContentView.Resources>
|
||||||
|
<StyleSheet
|
||||||
|
Source="./MemberList.css"/>
|
||||||
|
</ContentView.Resources>
|
||||||
|
<ContentView.Content>
|
||||||
|
<flv:FlowListView
|
||||||
|
x:Name="MembersList"
|
||||||
|
FlowColumnMinWidth="150"
|
||||||
|
RowHeight="150"
|
||||||
|
SeparatorVisibility="None"
|
||||||
|
BackgroundColor="#181818"
|
||||||
|
HasUnevenRows="false">
|
||||||
|
<flv:FlowListView.FlowColumnTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid
|
||||||
|
HorizontalOptions="FillAndExpand"
|
||||||
|
VerticalOptions="FillAndExpand">
|
||||||
|
<Label
|
||||||
|
Text="{Binding UserName}"/>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</flv:FlowListView.FlowColumnTemplate>
|
||||||
|
</flv:FlowListView>
|
||||||
|
</ContentView.Content>
|
||||||
|
</ContentView>
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Linq;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
using Aurora.Proto.Party;
|
||||||
|
using DLToolkit.Forms.Controls;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.MemberList
|
||||||
|
{
|
||||||
|
public partial class MemberList : ContentView
|
||||||
|
{
|
||||||
|
public MemberList()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bindable property for members list.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name=""Members""></param>
|
||||||
|
/// <param name="typeof(IEnumerable<string>"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static readonly BindableProperty MembersProperty =
|
||||||
|
BindableProperty.Create(propertyName: "Members",
|
||||||
|
returnType: typeof(ObservableCollection<Member>),
|
||||||
|
declaringType: typeof(MemberList),
|
||||||
|
defaultBindingMode: BindingMode.Default,
|
||||||
|
propertyChanged: OnMembersChanged);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Backing property for MembersProperty
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public ObservableCollection<Member> Members
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (ObservableCollection<Member>)GetValue(MembersProperty);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(MembersProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Memberes changed event handler. Assign member list source.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bindable"></param>
|
||||||
|
/// <param name="oldValue"></param>
|
||||||
|
/// <param name="newValue"></param>
|
||||||
|
private static void OnMembersChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
|
{
|
||||||
|
var control = (MemberList)bindable;
|
||||||
|
var membersList = control.FindByName("MembersList") as FlowListView;
|
||||||
|
|
||||||
|
if (newValue is ICollection source)
|
||||||
|
{
|
||||||
|
membersList.FlowItemsSource = source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.NavigationMenu
|
||||||
|
{
|
||||||
|
public class NavigationGroupItem : List<NavigationItem>
|
||||||
|
{
|
||||||
|
public NavigationGroupItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NavigationGroupItem(string heading)
|
||||||
|
{
|
||||||
|
GroupHeading = heading;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<NavigationItem> Items => this;
|
||||||
|
public string GroupHeading { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Aurora.Design.Views.Main;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.NavigationMenu
|
||||||
|
{
|
||||||
|
public class NavigationItem
|
||||||
|
{
|
||||||
|
public NavigationItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Group { get; set; }
|
||||||
|
public Type TargetType { get; set; }
|
||||||
|
public Type TargetViewModelType { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
ListView {
|
||||||
|
margin-left: 15;
|
||||||
|
margin-top: 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
#GroupTemplate {
|
||||||
|
align-items: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
#GroupCell Label {
|
||||||
|
color: lightgray;
|
||||||
|
font-size: 12;
|
||||||
|
font-family: Courier New, Courier, monospace;
|
||||||
|
font-style: italic;
|
||||||
|
padding-top: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ItemCell Label {
|
||||||
|
color: white;
|
||||||
|
font-size: 15;
|
||||||
|
font-family: Courier New, Courier, monospace;
|
||||||
|
font-style: normal;
|
||||||
|
text-align: left;
|
||||||
|
padding-top: 12;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ContentView
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
x:Class="Aurora.Design.Components.NavigationMenu.NavigationMenu">
|
||||||
|
<ContentView.Resources>
|
||||||
|
<StyleSheet
|
||||||
|
Source="NavigationMenu.css"/>
|
||||||
|
</ContentView.Resources>
|
||||||
|
<ContentView.Content>
|
||||||
|
<StackLayout
|
||||||
|
x:Name="Layout"
|
||||||
|
StyleClass="primaryColor">
|
||||||
|
<ListView
|
||||||
|
x:Name="MenuItemsListView"
|
||||||
|
HasUnevenRows="true"
|
||||||
|
SeparatorVisibility="None"
|
||||||
|
IsGroupingEnabled="true"
|
||||||
|
RowHeight="35"
|
||||||
|
StyleClass="primaryColor"
|
||||||
|
CachingStrategy="RecycleElement">
|
||||||
|
<ListView.GroupHeaderTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<ViewCell
|
||||||
|
x:Name="GroupCell">
|
||||||
|
<Label
|
||||||
|
VerticalTextAlignment="Center"
|
||||||
|
Text="{Binding GroupHeading}"/>
|
||||||
|
</ViewCell>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.GroupHeaderTemplate>
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<ViewCell
|
||||||
|
x:Name="ItemCell">
|
||||||
|
<Label
|
||||||
|
StyleClass="primaryColor"
|
||||||
|
Text="{Binding Title}"/>
|
||||||
|
</ViewCell>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
|
</StackLayout>
|
||||||
|
</ContentView.Content>
|
||||||
|
</ContentView>
|
||||||
Loaded 100 of 186 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user