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">
|
||||
<HintPath>..\packages\taglib-sharp-netstandard2.0.2.1.0\lib\netstandard2.0\taglib-sharp.dll</HintPath>
|
||||
</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="Microsoft.Threading.Tasks">
|
||||
<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="Xam.Plugins.Settings" version="3.1.1" 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" />
|
||||
</packages>
|
@ -10,7 +10,6 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Forms" Version="4.3.0.991211" />
|
||||
<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="LibVLCSharp.Forms" Version="3.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\Library\" />
|
||||
<Folder Include="Design\Views\Profile\" />
|
||||
<Folder Include="Design\Components\DataGrid\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Design\Components\MusicPlayer\Player.xaml.cs">
|
||||
@ -55,9 +55,15 @@
|
||||
<Protobuf Include="Proto\playback.proto" />
|
||||
<Protobuf Include="Proto\sync.proto" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Design\Resources\unselected.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Design\Components\NavigationMenu\NavigationMenu.css">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Design\Resources\unselected.png" />
|
||||
</ItemGroup>
|
||||
</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 {
|
||||
background-color: black
|
||||
Label {
|
||||
margin-left: 25;
|
||||
}
|
||||
|
@ -2,49 +2,92 @@
|
||||
<ContentView
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
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">
|
||||
<ContentView.Resources>
|
||||
<StyleSheet
|
||||
Source="Library.css"/>
|
||||
</ContentView.Resources>
|
||||
<ContentView.Content>
|
||||
<dg:DataGrid
|
||||
x:Name="LibraryDataGrid"
|
||||
SelectionEnabled="True"
|
||||
RowHeight="25"
|
||||
HeaderHeight="40"
|
||||
BorderColor="#CCCCCC"
|
||||
HeaderBackground="#E0E6F8">
|
||||
RowHeight="30"
|
||||
BorderColor="#3a3a3a"
|
||||
BorderThickness="0"
|
||||
HeaderFontSize="14"
|
||||
HeaderHeight="45"
|
||||
HeaderTextColor="White"
|
||||
HeaderBackground="#222222">
|
||||
<dg:DataGrid.GestureRecognizers>
|
||||
<TapGestureRecognizer
|
||||
NumberOfTapsRequired="2"/>
|
||||
</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:DataGridColumn
|
||||
Title=""
|
||||
PropertyName="Icon"
|
||||
Width="5">
|
||||
<dg:DataGridColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Image Source="../../Resources/unselected.png" />
|
||||
</DataTemplate>
|
||||
</dg:DataGridColumn.CellTemplate>
|
||||
</dg:DataGridColumn>
|
||||
|
||||
<dg:DataGridColumn
|
||||
Title="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
|
||||
Title="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
|
||||
Title="Artist"
|
||||
PropertyName="Metadata.Artist"
|
||||
Width="1*"/>
|
||||
<dg:DataGridColumn
|
||||
Title="Duration"
|
||||
PropertyName="Metadata.Duration"/>
|
||||
Width="1*">
|
||||
<dg:DataGridColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Label
|
||||
LineBreakMode="TailTruncation"
|
||||
Text="{Binding .}"
|
||||
HorizontalOptions="Start"
|
||||
VerticalOptions="Center"
|
||||
TextColor="White"/>
|
||||
</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>#F2F2F2</Color>
|
||||
<Color>#FFFFFF</Color>
|
||||
<Color>Transparent</Color>
|
||||
</dg:PaletteCollection>
|
||||
</dg:DataGrid.RowsBackgroundColorPalette>
|
||||
</dg:DataGrid>
|
||||
|
@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.DataGrid;
|
||||
using Aurora.Models.Media;
|
||||
|
||||
namespace Aurora.Design.Components.Library
|
||||
|
@ -14,7 +14,6 @@ ListView {
|
||||
|
||||
#GroupCell Label {
|
||||
color: lightgray;
|
||||
background-color: #232323;
|
||||
font-size: 12;
|
||||
font-family: Courier New, Courier, monospace;
|
||||
font-style: italic;
|
||||
@ -23,7 +22,6 @@ ListView {
|
||||
|
||||
#ItemCell label {
|
||||
color: white;
|
||||
background-color: #232323;
|
||||
font-size: 15;
|
||||
font-family: Courier New, Courier, monospace;
|
||||
font-style: normal;
|
||||
|
@ -11,7 +11,6 @@
|
||||
<StackLayout x:Name="Layout">
|
||||
<ListView
|
||||
x:Name="MenuItemsListView"
|
||||
SeparatorVisibility="None"
|
||||
HasUnevenRows="true"
|
||||
IsGroupingEnabled="true"
|
||||
RowHeight="35"
|
||||
|
@ -11,7 +11,6 @@ namespace Aurora.Design.Components.NavigationMenu
|
||||
{
|
||||
InitializeComponent();
|
||||
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:views="clr-namespace:Aurora.Design.Views.MainView"
|
||||
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">
|
||||
<ContentPage.Resources>
|
||||
<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;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user