Serious styling. Added data grid src for future modifications in performance
This commit is contained in:
parent
061adabff8
commit
b60f2a4f47
@ -79,9 +79,6 @@
|
|||||||
<Reference Include="taglib-sharp">
|
<Reference Include="taglib-sharp">
|
||||||
<HintPath>..\packages\taglib-sharp-netstandard2.0.2.1.0\lib\netstandard2.0\taglib-sharp.dll</HintPath>
|
<HintPath>..\packages\taglib-sharp-netstandard2.0.2.1.0\lib\netstandard2.0\taglib-sharp.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.Forms.DataGrid">
|
|
||||||
<HintPath>..\packages\Xamarin.Forms.DataGrid.3.1.0\lib\netstandard2.0\Xamarin.Forms.DataGrid.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="Microsoft.Threading.Tasks">
|
<Reference Include="Microsoft.Threading.Tasks">
|
||||||
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
|
||||||
|
@ -31,6 +31,5 @@
|
|||||||
<package id="VideoLAN.LibVLC.Mac" version="3.1.3.1" targetFramework="net47" />
|
<package id="VideoLAN.LibVLC.Mac" version="3.1.3.1" targetFramework="net47" />
|
||||||
<package id="Xam.Plugins.Settings" version="3.1.1" targetFramework="net47" />
|
<package id="Xam.Plugins.Settings" version="3.1.1" targetFramework="net47" />
|
||||||
<package id="Xamarin.Forms" version="4.3.0.991211" targetFramework="net47" />
|
<package id="Xamarin.Forms" version="4.3.0.991211" targetFramework="net47" />
|
||||||
<package id="Xamarin.Forms.DataGrid" version="3.1.0" targetFramework="net47" />
|
|
||||||
<package id="Xamarin.Forms.Platform.GTK" version="4.3.0.991211" targetFramework="net47" />
|
<package id="Xamarin.Forms.Platform.GTK" version="4.3.0.991211" targetFramework="net47" />
|
||||||
</packages>
|
</packages>
|
@ -10,7 +10,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Xamarin.Forms" Version="4.3.0.991211" />
|
<PackageReference Include="Xamarin.Forms" Version="4.3.0.991211" />
|
||||||
<PackageReference Include="Xamarin.Essentials" Version="1.3.1" />
|
<PackageReference Include="Xamarin.Essentials" Version="1.3.1" />
|
||||||
<PackageReference Include="Xamarin.Forms.DataGrid" Version="3.1.0" />
|
|
||||||
<PackageReference Include="taglib-sharp-netstandard2.0" Version="2.1.0" />
|
<PackageReference Include="taglib-sharp-netstandard2.0" Version="2.1.0" />
|
||||||
<PackageReference Include="LibVLCSharp.Forms" Version="3.3.1" />
|
<PackageReference Include="LibVLCSharp.Forms" Version="3.3.1" />
|
||||||
<PackageReference Include="VideoLAN.LibVLC.Mac" Version="3.1.3.1" />
|
<PackageReference Include="VideoLAN.LibVLC.Mac" Version="3.1.3.1" />
|
||||||
@ -42,6 +41,7 @@
|
|||||||
<Folder Include="Design\Components\MemberList\" />
|
<Folder Include="Design\Components\MemberList\" />
|
||||||
<Folder Include="Design\Components\Library\" />
|
<Folder Include="Design\Components\Library\" />
|
||||||
<Folder Include="Design\Views\Profile\" />
|
<Folder Include="Design\Views\Profile\" />
|
||||||
|
<Folder Include="Design\Components\DataGrid\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Design\Components\MusicPlayer\Player.xaml.cs">
|
<Compile Update="Design\Components\MusicPlayer\Player.xaml.cs">
|
||||||
@ -55,9 +55,15 @@
|
|||||||
<Protobuf Include="Proto\playback.proto" />
|
<Protobuf Include="Proto\playback.proto" />
|
||||||
<Protobuf Include="Proto\sync.proto" />
|
<Protobuf Include="Proto\sync.proto" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Design\Resources\unselected.png" />
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Update="Design\Components\NavigationMenu\NavigationMenu.css">
|
<EmbeddedResource Update="Design\Components\NavigationMenu\NavigationMenu.css">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Design\Resources\unselected.png" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
8
Aurora/Design/Components/DataGrid/ColumnCollection.cs
Normal file
8
Aurora/Design/Components/DataGrid/ColumnCollection.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public sealed class ColumnCollection : List<DataGridColumn>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
93
Aurora/Design/Components/DataGrid/DataGrid.xaml
Normal file
93
Aurora/Design/Components/DataGrid/DataGrid.xaml
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<?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>
|
||||||
|
<ContentView
|
||||||
|
x:Name="_noDataView"
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
IsVisible="False"/>
|
||||||
|
</Grid>
|
650
Aurora/Design/Components/DataGrid/DataGrid.xaml.cs
Normal file
650
Aurora/Design/Components/DataGrid/DataGrid.xaml.cs
Normal file
@ -0,0 +1,650 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
|
||||||
|
public event EventHandler Refreshing;
|
||||||
|
public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
|
||||||
|
|
||||||
|
#region Bindable properties
|
||||||
|
public static readonly BindableProperty ActiveRowColorProperty =
|
||||||
|
BindableProperty.Create(nameof(ActiveRowColor), typeof(Color), typeof(DataGrid), Color.FromRgb(128, 144, 160),
|
||||||
|
coerceValue: (b, v) =>
|
||||||
|
{
|
||||||
|
if (!(b as DataGrid).SelectionEnabled)
|
||||||
|
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set ActiveRowColor");
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty HeaderBackgroundProperty =
|
||||||
|
BindableProperty.Create(nameof(HeaderBackground), typeof(Color), typeof(DataGrid), Color.White,
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
if (self._headerView != null && !self.HeaderBordersVisible)
|
||||||
|
self._headerView.BackgroundColor = (Color)n;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty BorderColorProperty =
|
||||||
|
BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(DataGrid), Color.Black,
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
if (self.HeaderBordersVisible)
|
||||||
|
self._headerView.BackgroundColor = (Color)n;
|
||||||
|
|
||||||
|
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: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b 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: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b 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: (b, o, n) => (b as DataGrid).InitHeaderView(),
|
||||||
|
defaultValueCreator: b => { return new ColumnCollection(); }
|
||||||
|
);
|
||||||
|
|
||||||
|
public static readonly BindableProperty ItemsSourceProperty =
|
||||||
|
BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(DataGrid), null,
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
DataGrid self = b as DataGrid;
|
||||||
|
//ObservableCollection Tracking
|
||||||
|
if (o != null && o is INotifyCollectionChanged)
|
||||||
|
(o as INotifyCollectionChanged).CollectionChanged -= self.HandleItemsSourceCollectionChanged;
|
||||||
|
|
||||||
|
if (n != null)
|
||||||
|
{
|
||||||
|
if (n is INotifyCollectionChanged)
|
||||||
|
(n as INotifyCollectionChanged).CollectionChanged += self.HandleItemsSourceCollectionChanged;
|
||||||
|
|
||||||
|
self.InternalItems = new List<object>(((IEnumerable)n).Cast<object>());
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
void HandleItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
InternalItems = new List<object>(((IEnumerable)sender).Cast<object>());
|
||||||
|
if (SelectedItem != null && !InternalItems.Contains(SelectedItem))
|
||||||
|
SelectedItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly BindableProperty RowHeightProperty =
|
||||||
|
BindableProperty.Create(nameof(RowHeight), typeof(int), typeof(DataGrid), 40,
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
self._listView.RowHeight = (int)n;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
public static readonly BindableProperty HeaderHeightProperty =
|
||||||
|
BindableProperty.Create(nameof(HeaderHeight), typeof(int), typeof(DataGrid), 40,
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
self._headerView.HeightRequest = (int)n;
|
||||||
|
});
|
||||||
|
|
||||||
|
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: (b, v) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
if (!self.SelectionEnabled && v != null)
|
||||||
|
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set SelectedItem");
|
||||||
|
if (self.InternalItems != null && self.InternalItems.Contains(v))
|
||||||
|
return v;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
if (self._listView.SelectedItem != n)
|
||||||
|
self._listView.SelectedItem = n;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
public static readonly BindableProperty SelectionEnabledProperty =
|
||||||
|
BindableProperty.Create(nameof(SelectionEnabled), typeof(bool), typeof(DataGrid), true,
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b 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: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
if (n == null)
|
||||||
|
{
|
||||||
|
self._listView.IsPullToRefreshEnabled = false;
|
||||||
|
self._listView.RefreshCommand = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self._listView.IsPullToRefreshEnabled = true;
|
||||||
|
self._listView.RefreshCommand = n as ICommand;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty IsRefreshingProperty =
|
||||||
|
BindableProperty.Create(nameof(IsRefreshing), typeof(bool), typeof(DataGrid), false, BindingMode.TwoWay,
|
||||||
|
propertyChanged: (b, o, n) => (b as DataGrid)._listView.IsRefreshing = (bool)n);
|
||||||
|
|
||||||
|
public static readonly BindableProperty BorderThicknessProperty =
|
||||||
|
BindableProperty.Create(nameof(BorderThickness), typeof(Thickness), typeof(DataGrid), new Thickness(1),
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
(b as DataGrid)._headerView.ColumnSpacing = ((Thickness)n).HorizontalThickness / 2;
|
||||||
|
(b as DataGrid)._headerView.Padding = ((Thickness)n).HorizontalThickness / 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly BindableProperty HeaderBordersVisibleProperty =
|
||||||
|
BindableProperty.Create(nameof(HeaderBordersVisible), typeof(bool), typeof(DataGrid), true,
|
||||||
|
propertyChanged: (b, o, n) => (b as DataGrid)._headerView.BackgroundColor = (bool)n ? (b as DataGrid).BorderColor : (b as DataGrid).HeaderBackground);
|
||||||
|
|
||||||
|
public static readonly BindableProperty SortedColumnIndexProperty =
|
||||||
|
BindableProperty.Create(nameof(SortedColumnIndex), typeof(SortData), typeof(DataGrid), null, BindingMode.TwoWay,
|
||||||
|
validateValue: (b, v) =>
|
||||||
|
{
|
||||||
|
var self = b 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: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
if (o != n)
|
||||||
|
self.SortItems((SortData)n);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
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: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
var style = (n 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: (b, v) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
|
||||||
|
propertyChanged: (b, o, n) =>
|
||||||
|
{
|
||||||
|
var self = b as DataGrid;
|
||||||
|
if ((n as Style).Setters.Any(x => x.Property == Image.SourceProperty))
|
||||||
|
{
|
||||||
|
var style = (n 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: (b, o, n) =>
|
||||||
|
{
|
||||||
|
if (o != n)
|
||||||
|
(b as DataGrid)._noDataView.Content = n 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); }
|
||||||
|
}
|
||||||
|
|
||||||
|
IList<object> _internalItems;
|
||||||
|
|
||||||
|
internal IList<object> InternalItems
|
||||||
|
{
|
||||||
|
get { return _internalItems; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_internalItems = value;
|
||||||
|
|
||||||
|
if (IsSortable && SortedColumnIndex != null)
|
||||||
|
SortItems(SortedColumnIndex);
|
||||||
|
else
|
||||||
|
_listView.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 Fields
|
||||||
|
Dictionary<int, SortingOrder> _sortingOrders;
|
||||||
|
ListView _listView;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ctor
|
||||||
|
|
||||||
|
public DataGrid() : this(ListViewCachingStrategy.RecycleElement)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataGrid(ListViewCachingStrategy cachingStrategy)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
BackgroundColor = Color.Transparent;
|
||||||
|
|
||||||
|
_sortingOrders = new Dictionary<int, SortingOrder>();
|
||||||
|
|
||||||
|
_listView = new ListView(cachingStrategy)
|
||||||
|
{
|
||||||
|
BackgroundColor = Color.FromHex("#222222"),
|
||||||
|
ItemTemplate = new DataGridRowTemplateSelector(),
|
||||||
|
SeparatorVisibility = SeparatorVisibility.Default,
|
||||||
|
};
|
||||||
|
|
||||||
|
_listView.ItemSelected += (s, e) =>
|
||||||
|
{
|
||||||
|
if (SelectionEnabled)
|
||||||
|
SelectedItem = _listView.SelectedItem;
|
||||||
|
else
|
||||||
|
_listView.SelectedItem = null;
|
||||||
|
|
||||||
|
ItemSelected?.Invoke(this, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
_listView.Refreshing += (s, e) =>
|
||||||
|
{
|
||||||
|
Refreshing?.Invoke(this, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
_listView.SetBinding(ListView.RowHeightProperty, new Binding("RowHeight", source: this));
|
||||||
|
Grid.SetRow(_listView, 1);
|
||||||
|
Children.Add(_listView);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UI Methods
|
||||||
|
protected override void OnParentSet()
|
||||||
|
{
|
||||||
|
base.OnParentSet();
|
||||||
|
InitHeaderView();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnBindingContextChanged()
|
||||||
|
{
|
||||||
|
base.OnBindingContextChanged();
|
||||||
|
SetColumnsBindingContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Reload()
|
||||||
|
{
|
||||||
|
InternalItems = new List<object>(_internalItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Header Creation Methods
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
#region Sorting methods
|
||||||
|
internal 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;
|
||||||
|
|
||||||
|
_listView.ItemsSource = _internalItems;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
129
Aurora/Design/Components/DataGrid/DataGridColumn.cs
Normal file
129
Aurora/Design/Components/DataGrid/DataGridColumn.cs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
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: (b, o, n) => { if (o != n) (b 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
Aurora/Design/Components/DataGrid/DataGridComponent.cs
Normal file
12
Aurora/Design/Components/DataGrid/DataGridComponent.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public static class DataGridComponent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// You should call this method for loding the assembly
|
||||||
|
/// </summary>
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
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)
|
||||||
|
{
|
||||||
|
var listView = container as ListView;
|
||||||
|
var 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
152
Aurora/Design/Components/DataGrid/DataGridViewCell.cs
Normal file
152
Aurora/Design/Components/DataGrid/DataGridViewCell.cs
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
8
Aurora/Design/Components/DataGrid/IColorProvider.cs
Normal file
8
Aurora/Design/Components/DataGrid/IColorProvider.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
using Xamarin.Forms;
|
||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public interface IColorProvider
|
||||||
|
{
|
||||||
|
Color GetColor(int rowIndex, object item);
|
||||||
|
}
|
||||||
|
}
|
17
Aurora/Design/Components/DataGrid/PaletteCollection.cs
Normal file
17
Aurora/Design/Components/DataGrid/PaletteCollection.cs
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
Aurora/Design/Components/DataGrid/SortData.cs
Normal file
51
Aurora/Design/Components/DataGrid/SortData.cs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
24
Aurora/Design/Components/DataGrid/SortDataTypeConverter.cs
Normal file
24
Aurora/Design/Components/DataGrid/SortDataTypeConverter.cs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
Aurora/Design/Components/DataGrid/SortingOrder.cs
Normal file
9
Aurora/Design/Components/DataGrid/SortingOrder.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Aurora.Design.Components.DataGrid
|
||||||
|
{
|
||||||
|
public enum SortingOrder
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Ascendant = 1,
|
||||||
|
Descendant = 2,
|
||||||
|
}
|
||||||
|
}
|
BIN
Aurora/Design/Components/DataGrid/down.png
Normal file
BIN
Aurora/Design/Components/DataGrid/down.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
BIN
Aurora/Design/Components/DataGrid/up.png
Normal file
BIN
Aurora/Design/Components/DataGrid/up.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
@ -1,3 +1,3 @@
|
|||||||
#LibraryDataGrid {
|
Label {
|
||||||
background-color: black
|
margin-left: 25;
|
||||||
}
|
}
|
||||||
|
@ -2,49 +2,92 @@
|
|||||||
<ContentView
|
<ContentView
|
||||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:dg="clr-namespace:Xamarin.Forms.DataGrid;assembly=Xamarin.Forms.DataGrid"
|
xmlns:dg="clr-namespace:Aurora.Design.Components.DataGrid"
|
||||||
x:Class="Aurora.Design.Components.Library.Library">
|
x:Class="Aurora.Design.Components.Library.Library">
|
||||||
|
<ContentView.Resources>
|
||||||
|
<StyleSheet
|
||||||
|
Source="Library.css"/>
|
||||||
|
</ContentView.Resources>
|
||||||
<ContentView.Content>
|
<ContentView.Content>
|
||||||
<dg:DataGrid
|
<dg:DataGrid
|
||||||
x:Name="LibraryDataGrid"
|
x:Name="LibraryDataGrid"
|
||||||
SelectionEnabled="True"
|
SelectionEnabled="True"
|
||||||
RowHeight="25"
|
RowHeight="30"
|
||||||
HeaderHeight="40"
|
BorderColor="#3a3a3a"
|
||||||
BorderColor="#CCCCCC"
|
BorderThickness="0"
|
||||||
HeaderBackground="#E0E6F8">
|
HeaderFontSize="14"
|
||||||
|
HeaderHeight="45"
|
||||||
|
HeaderTextColor="White"
|
||||||
|
HeaderBackground="#222222">
|
||||||
<dg:DataGrid.GestureRecognizers>
|
<dg:DataGrid.GestureRecognizers>
|
||||||
<TapGestureRecognizer
|
<TapGestureRecognizer
|
||||||
NumberOfTapsRequired="2"/>
|
NumberOfTapsRequired="2"/>
|
||||||
</dg:DataGrid.GestureRecognizers>
|
</dg:DataGrid.GestureRecognizers>
|
||||||
<dg:DataGrid.HeaderFontSize>
|
|
||||||
<OnIdiom
|
|
||||||
x:TypeArguments="x:Double">
|
|
||||||
<OnIdiom.Tablet>15</OnIdiom.Tablet>
|
|
||||||
<OnIdiom.Phone>13</OnIdiom.Phone>
|
|
||||||
<OnIdiom.Desktop>20</OnIdiom.Desktop>
|
|
||||||
</OnIdiom>
|
|
||||||
</dg:DataGrid.HeaderFontSize>
|
|
||||||
<dg:DataGrid.Columns>
|
<dg:DataGrid.Columns>
|
||||||
|
<dg:DataGridColumn
|
||||||
|
Title=""
|
||||||
|
PropertyName="Icon"
|
||||||
|
Width="5">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Image Source="../../Resources/unselected.png" />
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
|
||||||
<dg:DataGridColumn
|
<dg:DataGridColumn
|
||||||
Title="Title"
|
Title="Title"
|
||||||
PropertyName="Metadata.Title"
|
PropertyName="Metadata.Title"
|
||||||
Width="2*"/>
|
Width="2*">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Text="{Binding .}"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
VerticalOptions="Center"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
|
||||||
<dg:DataGridColumn
|
<dg:DataGridColumn
|
||||||
Title="Album"
|
Title="Album"
|
||||||
PropertyName="Metadata.Album"
|
PropertyName="Metadata.Album"
|
||||||
Width="0.95*"/>
|
Width="0.95*">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Text="{Binding .}"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
VerticalOptions="Center"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
<dg:DataGridColumn
|
<dg:DataGridColumn
|
||||||
Title="Artist"
|
Title="Artist"
|
||||||
PropertyName="Metadata.Artist"
|
PropertyName="Metadata.Artist"
|
||||||
Width="1*"/>
|
Width="1*">
|
||||||
<dg:DataGridColumn
|
<dg:DataGridColumn.CellTemplate>
|
||||||
Title="Duration"
|
<DataTemplate>
|
||||||
PropertyName="Metadata.Duration"/>
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Text="{Binding .}"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
TextColor="White"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
</dg:DataGrid.Columns>
|
</dg:DataGrid.Columns>
|
||||||
|
<dg:DataGrid.RowsTextColorPalette>
|
||||||
|
<dg:PaletteCollection>
|
||||||
|
<Color>White</Color>
|
||||||
|
</dg:PaletteCollection>
|
||||||
|
</dg:DataGrid.RowsTextColorPalette>
|
||||||
<dg:DataGrid.RowsBackgroundColorPalette>
|
<dg:DataGrid.RowsBackgroundColorPalette>
|
||||||
<dg:PaletteCollection>
|
<dg:PaletteCollection>
|
||||||
<Color>#F2F2F2</Color>
|
<Color>Transparent</Color>
|
||||||
<Color>#FFFFFF</Color>
|
|
||||||
</dg:PaletteCollection>
|
</dg:PaletteCollection>
|
||||||
</dg:DataGrid.RowsBackgroundColorPalette>
|
</dg:DataGrid.RowsBackgroundColorPalette>
|
||||||
</dg:DataGrid>
|
</dg:DataGrid>
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using Xamarin.Forms.DataGrid;
|
|
||||||
using Aurora.Models.Media;
|
using Aurora.Models.Media;
|
||||||
|
|
||||||
namespace Aurora.Design.Components.Library
|
namespace Aurora.Design.Components.Library
|
||||||
|
@ -14,7 +14,6 @@ ListView {
|
|||||||
|
|
||||||
#GroupCell Label {
|
#GroupCell Label {
|
||||||
color: lightgray;
|
color: lightgray;
|
||||||
background-color: #232323;
|
|
||||||
font-size: 12;
|
font-size: 12;
|
||||||
font-family: Courier New, Courier, monospace;
|
font-family: Courier New, Courier, monospace;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
@ -23,7 +22,6 @@ ListView {
|
|||||||
|
|
||||||
#ItemCell label {
|
#ItemCell label {
|
||||||
color: white;
|
color: white;
|
||||||
background-color: #232323;
|
|
||||||
font-size: 15;
|
font-size: 15;
|
||||||
font-family: Courier New, Courier, monospace;
|
font-family: Courier New, Courier, monospace;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
<StackLayout x:Name="Layout">
|
<StackLayout x:Name="Layout">
|
||||||
<ListView
|
<ListView
|
||||||
x:Name="MenuItemsListView"
|
x:Name="MenuItemsListView"
|
||||||
SeparatorVisibility="None"
|
|
||||||
HasUnevenRows="true"
|
HasUnevenRows="true"
|
||||||
IsGroupingEnabled="true"
|
IsGroupingEnabled="true"
|
||||||
RowHeight="35"
|
RowHeight="35"
|
||||||
|
@ -11,7 +11,6 @@ namespace Aurora.Design.Components.NavigationMenu
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
ListView = MenuItemsListView;
|
ListView = MenuItemsListView;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BIN
Aurora/Design/Resources/unselected.png
Normal file
BIN
Aurora/Design/Resources/unselected.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
@ -4,7 +4,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:views="clr-namespace:Aurora.Design.Views.MainView"
|
xmlns:views="clr-namespace:Aurora.Design.Views.MainView"
|
||||||
xmlns:navigation="clr-namespace:Aurora.Design.Components.NavigationMenu"
|
xmlns:navigation="clr-namespace:Aurora.Design.Components.NavigationMenu"
|
||||||
xmlns:mp="clr-namespace:Aurora.Design.Components.MediaPlayer"
|
xmlns:mp="clr-namespace:Aurora.Design.Components.MediaPlayer"
|
||||||
x:Class="Aurora.Design.Views.Main.MainView">
|
x:Class="Aurora.Design.Views.Main.MainView">
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
<StyleSheet
|
<StyleSheet
|
||||||
|
77
Aurora/Utils/ReflectionUtils.cs
Normal file
77
Aurora/Utils/ReflectionUtils.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Aurora.Utils
|
||||||
|
{
|
||||||
|
public static class ReflectionUtils
|
||||||
|
{
|
||||||
|
private const char IndexBeginOp = '[';
|
||||||
|
private const char IndexEndOp = ']';
|
||||||
|
private const char PropertyOfOp = '.';
|
||||||
|
|
||||||
|
public static object GetValueByPath(object obj, string path)
|
||||||
|
{
|
||||||
|
object result = obj;
|
||||||
|
var tokens = path?.Split(IndexBeginOp, PropertyOfOp).ToList();
|
||||||
|
foreach (var token in tokens)
|
||||||
|
{
|
||||||
|
if (result == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Property
|
||||||
|
if (!token.Contains(IndexEndOp.ToString()))
|
||||||
|
{
|
||||||
|
result = GetPropertyValue(result, token);
|
||||||
|
}
|
||||||
|
// Index
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = GetIndexValue(result, token.Replace(IndexEndOp.ToString(), ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GetPropertyValue(object obj, string propertyName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return obj?.GetType().GetRuntimeProperty(propertyName)?.GetValue(obj);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GetIndexValue(object obj, string index)
|
||||||
|
{
|
||||||
|
object result = null;
|
||||||
|
var indexOperator = obj?.GetType().GetRuntimeProperty("Item");
|
||||||
|
if (indexOperator != null)
|
||||||
|
{
|
||||||
|
var indexParameters = indexOperator.GetIndexParameters();
|
||||||
|
// Looking up suitable index operator
|
||||||
|
foreach (var parameter in indexParameters)
|
||||||
|
{
|
||||||
|
bool isIndexOpWorked = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var indexVal = Convert.ChangeType(index, parameter.ParameterType);
|
||||||
|
result = indexOperator.GetValue(obj, new object[] { indexVal });
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
isIndexOpWorked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the index operator worked, skip looking up others
|
||||||
|
if (isIndexOpWorked)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user