parent
3b8fe7fb97
commit
9e75dd66c0
@ -87,7 +87,7 @@
|
|||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</Grid.Resources>
|
</Grid.Resources>
|
||||||
</Grid>
|
</Grid>
|
||||||
<!-- <ListView x:Name="DataList" Grid.Row="1" BackgroundColor="#222222" /> -->
|
<ListView x:Name="DataList" Grid.Row="1" BackgroundColor="#222222" />
|
||||||
<ContentView
|
<ContentView
|
||||||
x:Name="_noDataView"
|
x:Name="_noDataView"
|
||||||
Grid.RowSpan="2"
|
Grid.RowSpan="2"
|
||||||
|
@ -2,127 +2,230 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using Aurora.Utils;
|
using Aurora.Utils;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Xamarin.Forms.DataGrid.UnitTest")]
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
namespace Aurora.Design.Components.DataGrid
|
||||||
{
|
{
|
||||||
public partial class DataGrid : Grid
|
public partial class DataGrid : Grid
|
||||||
{
|
{
|
||||||
|
#region Private Fields
|
||||||
|
private ObservableCollection<object> _internalItems;
|
||||||
|
|
||||||
|
private Dictionary<int, SortingOrder> _sortingOrders;
|
||||||
|
|
||||||
|
#endregion Fields
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
public DataGrid() : this(ListViewCachingStrategy.RetainElement)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataGrid(ListViewCachingStrategy cachingStrategy)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
BackgroundColor = Color.Transparent;
|
||||||
|
|
||||||
|
_sortingOrders = new Dictionary<int, SortingOrder>();
|
||||||
|
|
||||||
|
DataList.ItemTemplate = new DataGridRowTemplateSelector();
|
||||||
|
|
||||||
|
DataList.ItemSelected += (s, e) =>
|
||||||
|
{
|
||||||
|
if (SelectionEnabled)
|
||||||
|
{
|
||||||
|
SelectedItem = DataList.SelectedItem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DataList.SelectedItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemSelected?.Invoke(this, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
DataList.Refreshing += (s, e) =>
|
||||||
|
{
|
||||||
|
Refreshing?.Invoke(this, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
DataList.SetBinding(ListView.RowHeightProperty, new Binding("RowHeight", source: this));
|
||||||
|
}
|
||||||
|
#endregion Constructor
|
||||||
|
|
||||||
|
#region Public Fields
|
||||||
public event EventHandler Refreshing;
|
public event EventHandler Refreshing;
|
||||||
public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
|
public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
|
||||||
|
|
||||||
|
#endregion Public Fields
|
||||||
|
|
||||||
#region Bindable properties
|
#region Bindable properties
|
||||||
public static readonly BindableProperty ActiveRowColorProperty =
|
public static readonly BindableProperty ActiveRowColorProperty =
|
||||||
BindableProperty.Create(nameof(ActiveRowColor), typeof(Color), typeof(DataGrid), Color.FromRgb(128, 144, 160),
|
BindableProperty.Create(
|
||||||
coerceValue: (b, v) =>
|
nameof(ActiveRowColor),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(DataGrid),
|
||||||
|
Color.FromRgb(128, 144, 160),
|
||||||
|
coerceValue: (bindable, value) =>
|
||||||
{
|
{
|
||||||
if (!(b as DataGrid).SelectionEnabled)
|
if (!(bindable as DataGrid).SelectionEnabled)
|
||||||
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set ActiveRowColor");
|
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set ActiveRowColor");
|
||||||
return v;
|
return value;
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty HeaderBackgroundProperty =
|
public static readonly BindableProperty HeaderBackgroundProperty =
|
||||||
BindableProperty.Create(nameof(HeaderBackground), typeof(Color), typeof(DataGrid), Color.White,
|
BindableProperty.Create(
|
||||||
propertyChanged: (b, o, n) =>
|
nameof(HeaderBackground),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(DataGrid),
|
||||||
|
Color.White,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if (self._headerView != null && !self.HeaderBordersVisible)
|
if (self._headerView != null && !self.HeaderBordersVisible)
|
||||||
self._headerView.BackgroundColor = (Color)n;
|
self._headerView.BackgroundColor = (Color)newValue;
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty BorderColorProperty =
|
public static readonly BindableProperty BorderColorProperty =
|
||||||
BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(DataGrid), Color.Black,
|
BindableProperty.Create(
|
||||||
propertyChanged: (b, o, n) =>
|
nameof(BorderColor),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(DataGrid),
|
||||||
|
Color.Black,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if (self.HeaderBordersVisible)
|
if (self.HeaderBordersVisible)
|
||||||
self._headerView.BackgroundColor = (Color)n;
|
self._headerView.BackgroundColor = (Color)newValue;
|
||||||
|
|
||||||
if (self.Columns != null && self.ItemsSource != null)
|
if (self.Columns != null && self.ItemsSource != null)
|
||||||
self.Reload();
|
self.Reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty RowsBackgroundColorPaletteProperty =
|
public static readonly BindableProperty RowsBackgroundColorPaletteProperty =
|
||||||
BindableProperty.Create(nameof(RowsBackgroundColorPalette), typeof(IColorProvider), typeof(DataGrid), new PaletteCollection { default(Color) },
|
BindableProperty.Create(nameof(RowsBackgroundColorPalette),
|
||||||
propertyChanged: (b, o, n) =>
|
typeof(IColorProvider),
|
||||||
|
typeof(DataGrid),
|
||||||
|
new PaletteCollection { default(Color) },
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if (self.Columns != null && self.ItemsSource != null)
|
if (self.Columns != null && self.ItemsSource != null)
|
||||||
self.Reload();
|
self.Reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty RowsTextColorPaletteProperty =
|
public static readonly BindableProperty RowsTextColorPaletteProperty =
|
||||||
BindableProperty.Create(nameof(RowsTextColorPalette), typeof(IColorProvider), typeof(DataGrid), new PaletteCollection { Color.Black },
|
BindableProperty.Create(
|
||||||
propertyChanged: (b, o, n) =>
|
nameof(RowsTextColorPalette),
|
||||||
|
typeof(IColorProvider),
|
||||||
|
typeof(DataGrid),
|
||||||
|
new PaletteCollection { Color.Black },
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if (self.Columns != null && self.ItemsSource != null)
|
if (self.Columns != null && self.ItemsSource != null)
|
||||||
self.Reload();
|
self.Reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty ColumnsProperty =
|
public static readonly BindableProperty ColumnsProperty =
|
||||||
BindableProperty.Create(nameof(Columns), typeof(ColumnCollection), typeof(DataGrid),
|
BindableProperty.Create(
|
||||||
propertyChanged: (b, o, n) => (b as DataGrid).InitHeaderView(),
|
nameof(Columns),
|
||||||
defaultValueCreator: b => { return new ColumnCollection(); }
|
typeof(ColumnCollection),
|
||||||
|
typeof(DataGrid),
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
(bindable as DataGrid).InitHeaderView();
|
||||||
|
},
|
||||||
|
defaultValueCreator: bindable => { return new ColumnCollection(); }
|
||||||
);
|
);
|
||||||
|
|
||||||
public static readonly BindableProperty ItemsSourceProperty =
|
public static BindableProperty ItemsSourceProperty =
|
||||||
BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(DataGrid), null,
|
BindableProperty.Create(
|
||||||
propertyChanged: (b, o, n) =>
|
propertyName: nameof(ItemsSource),
|
||||||
|
returnType: typeof(IEnumerable),
|
||||||
|
declaringType: typeof(DataGrid),
|
||||||
|
defaultBindingMode: BindingMode.TwoWay,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
DataGrid self = b as DataGrid;
|
DataGrid self = bindable as DataGrid;
|
||||||
//ObservableCollection Tracking
|
//ObservableCollection Tracking
|
||||||
if (o != null && o is INotifyCollectionChanged)
|
if (oldValue != null && oldValue is INotifyCollectionChanged)
|
||||||
(o as INotifyCollectionChanged).CollectionChanged -= self.HandleItemsSourceCollectionChanged;
|
|
||||||
|
|
||||||
if (n != null)
|
|
||||||
{
|
{
|
||||||
if (n is INotifyCollectionChanged)
|
(oldValue as INotifyCollectionChanged).CollectionChanged -= self.HandleItemsSourceCollectionChanged;
|
||||||
(n as INotifyCollectionChanged).CollectionChanged += self.HandleItemsSourceCollectionChanged;
|
}
|
||||||
|
|
||||||
self.InternalItems = new List<object>(((IEnumerable)n).Cast<object>());
|
if (newValue != null && newValue is INotifyCollectionChanged)
|
||||||
|
{
|
||||||
|
(newValue as INotifyCollectionChanged).CollectionChanged += self.HandleItemsSourceCollectionChanged;
|
||||||
|
|
||||||
|
self.InternalItems = new ObservableCollection<object>(((IEnumerable<object>)newValue));
|
||||||
|
//Assign listview item source
|
||||||
|
self.DataList.ItemsSource = self.InternalItems;
|
||||||
|
self.DataList.SetBinding(ListView.ItemsSourceProperty, new Binding("ItemsSource", source: self));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.SelectedItem != null && !self.InternalItems.Contains(self.SelectedItem))
|
if (self.SelectedItem != null && !self.InternalItems.Contains(self.SelectedItem))
|
||||||
|
{
|
||||||
self.SelectedItem = null;
|
self.SelectedItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.NoDataView != null)
|
if (self.NoDataView != null)
|
||||||
{
|
{
|
||||||
if (self.ItemsSource == null || self.InternalItems.Count() == 0)
|
if (self.ItemsSource == null || self.InternalItems.Count() == 0)
|
||||||
|
{
|
||||||
self._noDataView.IsVisible = true;
|
self._noDataView.IsVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
else if (self._noDataView.IsVisible)
|
else if (self._noDataView.IsVisible)
|
||||||
|
{
|
||||||
self._noDataView.IsVisible = false;
|
self._noDataView.IsVisible = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
private void HandleItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
void HandleItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
InternalItems = new List<object>(((IEnumerable)sender).Cast<object>());
|
|
||||||
|
if (e.NewItems != null)
|
||||||
|
{
|
||||||
|
foreach (object item in e.NewItems)
|
||||||
|
{
|
||||||
|
InternalItems.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.OldItems != null)
|
||||||
|
{
|
||||||
|
foreach (object item in e.OldItems)
|
||||||
|
{
|
||||||
|
InternalItems.Remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (SelectedItem != null && !InternalItems.Contains(SelectedItem))
|
if (SelectedItem != null && !InternalItems.Contains(SelectedItem))
|
||||||
|
{
|
||||||
SelectedItem = null;
|
SelectedItem = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly BindableProperty RowHeightProperty =
|
public static readonly BindableProperty RowHeightProperty =
|
||||||
BindableProperty.Create(nameof(RowHeight), typeof(int), typeof(DataGrid), 40,
|
BindableProperty.Create(nameof(RowHeight), typeof(int), typeof(DataGrid), 40,
|
||||||
propertyChanged: (b, o, n) =>
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
self._listView.RowHeight = (int)n;
|
self.DataList.RowHeight = (int)newValue;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
public static readonly BindableProperty HeaderHeightProperty =
|
public static readonly BindableProperty HeaderHeightProperty =
|
||||||
BindableProperty.Create(nameof(HeaderHeight), typeof(int), typeof(DataGrid), 40,
|
BindableProperty.Create(nameof(HeaderHeight), typeof(int), typeof(DataGrid), 40,
|
||||||
propertyChanged: (b, o, n) =>
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
self._headerView.HeightRequest = (int)n;
|
self._headerView.HeightRequest = (int)newValue;
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty IsSortableProperty =
|
public static readonly BindableProperty IsSortableProperty =
|
||||||
@ -132,75 +235,115 @@ namespace Aurora.Design.Components.DataGrid
|
|||||||
BindableProperty.Create(nameof(FontSize), typeof(double), typeof(DataGrid), 13.0);
|
BindableProperty.Create(nameof(FontSize), typeof(double), typeof(DataGrid), 13.0);
|
||||||
|
|
||||||
public static readonly BindableProperty FontFamilyProperty =
|
public static readonly BindableProperty FontFamilyProperty =
|
||||||
BindableProperty.Create(nameof(FontFamily), typeof(string), typeof(DataGrid), Font.Default.FontFamily);
|
BindableProperty.Create(
|
||||||
|
nameof(FontFamily),
|
||||||
|
typeof(string),
|
||||||
|
typeof(DataGrid),
|
||||||
|
Font.Default.FontFamily);
|
||||||
|
|
||||||
public static readonly BindableProperty SelectedItemProperty =
|
public static readonly BindableProperty SelectedItemProperty =
|
||||||
BindableProperty.Create(nameof(SelectedItem), typeof(object), typeof(DataGrid), null, BindingMode.TwoWay,
|
BindableProperty.Create(
|
||||||
coerceValue: (b, v) =>
|
nameof(SelectedItem),
|
||||||
|
typeof(object),
|
||||||
|
typeof(DataGrid),
|
||||||
|
null,
|
||||||
|
BindingMode.TwoWay,
|
||||||
|
coerceValue: (bindable, value) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if (!self.SelectionEnabled && v != null)
|
if (!self.SelectionEnabled && value != null)
|
||||||
|
{
|
||||||
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set SelectedItem");
|
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set SelectedItem");
|
||||||
if (self.InternalItems != null && self.InternalItems.Contains(v))
|
}
|
||||||
return v;
|
if (self.InternalItems != null && self.InternalItems.Contains(value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
propertyChanged: (b, o, n) =>
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if (self._listView.SelectedItem != n)
|
if (self.DataList.SelectedItem != newValue)
|
||||||
self._listView.SelectedItem = n;
|
{
|
||||||
|
self.DataList.SelectedItem = newValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
public static readonly BindableProperty SelectionEnabledProperty =
|
public static readonly BindableProperty SelectionEnabledProperty =
|
||||||
BindableProperty.Create(nameof(SelectionEnabled), typeof(bool), typeof(DataGrid), true,
|
BindableProperty.Create(nameof(SelectionEnabled), typeof(bool), typeof(DataGrid), true,
|
||||||
propertyChanged: (b, o, n) =>
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if (!self.SelectionEnabled && self.SelectedItem != null)
|
if (!self.SelectionEnabled && self.SelectedItem != null)
|
||||||
|
{
|
||||||
self.SelectedItem = null;
|
self.SelectedItem = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty PullToRefreshCommandProperty =
|
public static readonly BindableProperty PullToRefreshCommandProperty =
|
||||||
BindableProperty.Create(nameof(PullToRefreshCommand), typeof(ICommand), typeof(DataGrid), null,
|
BindableProperty.Create(nameof(PullToRefreshCommand), typeof(ICommand), typeof(DataGrid), null,
|
||||||
propertyChanged: (b, o, n) =>
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if (n == null)
|
if (newValue == null)
|
||||||
{
|
{
|
||||||
self._listView.IsPullToRefreshEnabled = false;
|
self.DataList.IsPullToRefreshEnabled = false;
|
||||||
self._listView.RefreshCommand = null;
|
self.DataList.RefreshCommand = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self._listView.IsPullToRefreshEnabled = true;
|
self.DataList.IsPullToRefreshEnabled = true;
|
||||||
self._listView.RefreshCommand = n as ICommand;
|
self.DataList.RefreshCommand = newValue as ICommand;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty IsRefreshingProperty =
|
public static readonly BindableProperty IsRefreshingProperty =
|
||||||
BindableProperty.Create(nameof(IsRefreshing), typeof(bool), typeof(DataGrid), false, BindingMode.TwoWay,
|
BindableProperty.Create(
|
||||||
propertyChanged: (b, o, n) => (b as DataGrid)._listView.IsRefreshing = (bool)n);
|
nameof(IsRefreshing),
|
||||||
|
typeof(bool),
|
||||||
|
typeof(DataGrid),
|
||||||
|
false,
|
||||||
|
BindingMode.TwoWay,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
|
{
|
||||||
|
(bindable as DataGrid).DataList.IsRefreshing = (bool)newValue;
|
||||||
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty BorderThicknessProperty =
|
public static readonly BindableProperty BorderThicknessProperty =
|
||||||
BindableProperty.Create(nameof(BorderThickness), typeof(Thickness), typeof(DataGrid), new Thickness(1),
|
BindableProperty.Create(
|
||||||
propertyChanged: (b, o, n) =>
|
nameof(BorderThickness),
|
||||||
|
typeof(Thickness),
|
||||||
|
typeof(DataGrid),
|
||||||
|
new Thickness(1),
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
(b as DataGrid)._headerView.ColumnSpacing = ((Thickness)n).HorizontalThickness / 2;
|
(bindable as DataGrid)._headerView.ColumnSpacing = ((Thickness)newValue).HorizontalThickness / 2;
|
||||||
(b as DataGrid)._headerView.Padding = ((Thickness)n).HorizontalThickness / 2;
|
(bindable as DataGrid)._headerView.Padding = ((Thickness)newValue).HorizontalThickness / 2;
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly BindableProperty HeaderBordersVisibleProperty =
|
public static readonly BindableProperty HeaderBordersVisibleProperty =
|
||||||
BindableProperty.Create(nameof(HeaderBordersVisible), typeof(bool), typeof(DataGrid), true,
|
BindableProperty.Create(
|
||||||
propertyChanged: (b, o, n) => (b as DataGrid)._headerView.BackgroundColor = (bool)n ? (b as DataGrid).BorderColor : (b as DataGrid).HeaderBackground);
|
nameof(HeaderBordersVisible),
|
||||||
|
typeof(bool),
|
||||||
|
typeof(DataGrid),
|
||||||
|
true,
|
||||||
|
propertyChanged: (bindable, oldValue, newValue) => (bindable as DataGrid)._headerView.BackgroundColor = (bool)newValue ? (bindable as DataGrid).BorderColor : (bindable as DataGrid).HeaderBackground);
|
||||||
|
|
||||||
public static readonly BindableProperty SortedColumnIndexProperty =
|
public static readonly BindableProperty SortedColumnIndexProperty =
|
||||||
BindableProperty.Create(nameof(SortedColumnIndex), typeof(SortData), typeof(DataGrid), null, BindingMode.TwoWay,
|
BindableProperty.Create(
|
||||||
validateValue: (b, v) =>
|
nameof(SortedColumnIndex),
|
||||||
|
typeof(SortData),
|
||||||
|
typeof(DataGrid),
|
||||||
|
null,
|
||||||
|
BindingMode.TwoWay,
|
||||||
|
validateValue: (bindable, v) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
var sData = (SortData)v;
|
var sData = (SortData)v;
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -209,11 +352,11 @@ namespace Aurora.Design.Components.DataGrid
|
|||||||
self.Columns.Count == 0 || //columns not setted yet
|
self.Columns.Count == 0 || //columns not setted yet
|
||||||
(sData.Index < self.Columns.Count && self.Columns.ElementAt(sData.Index).SortingEnabled);
|
(sData.Index < self.Columns.Count && self.Columns.ElementAt(sData.Index).SortingEnabled);
|
||||||
},
|
},
|
||||||
propertyChanged: (b, o, n) =>
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if (o != n)
|
if (oldValue != newValue)
|
||||||
self.SortItems((SortData)n);
|
self.SortItems((SortData)newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -221,18 +364,28 @@ namespace Aurora.Design.Components.DataGrid
|
|||||||
BindableProperty.Create(nameof(HeaderLabelStyle), typeof(Style), typeof(DataGrid));
|
BindableProperty.Create(nameof(HeaderLabelStyle), typeof(Style), typeof(DataGrid));
|
||||||
|
|
||||||
public static readonly BindableProperty AscendingIconProperty =
|
public static readonly BindableProperty AscendingIconProperty =
|
||||||
BindableProperty.Create(nameof(AscendingIcon), typeof(ImageSource), typeof(DataGrid), ImageSource.FromResource("Xamarin.Forms.DataGrid.up.png", typeof(DataGrid).GetTypeInfo().Assembly));
|
BindableProperty.Create(
|
||||||
|
nameof(AscendingIcon),
|
||||||
|
typeof(ImageSource),
|
||||||
|
typeof(DataGrid),
|
||||||
|
ImageSource.FromResource("Xamarin.Forms.DataGrid.up.png",
|
||||||
|
typeof(DataGrid).GetTypeInfo().Assembly));
|
||||||
|
|
||||||
public static readonly BindableProperty DescendingIconProperty =
|
public static readonly BindableProperty DescendingIconProperty =
|
||||||
BindableProperty.Create(nameof(DescendingIcon), typeof(ImageSource), typeof(DataGrid), ImageSource.FromResource("Xamarin.Forms.DataGrid.down.png", typeof(DataGrid).GetTypeInfo().Assembly));
|
BindableProperty.Create(
|
||||||
|
nameof(DescendingIcon),
|
||||||
|
typeof(ImageSource),
|
||||||
|
typeof(DataGrid),
|
||||||
|
ImageSource.FromResource("Xamarin.Forms.DataGrid.down.png",
|
||||||
|
typeof(DataGrid).GetTypeInfo().Assembly));
|
||||||
|
|
||||||
public static readonly BindableProperty DescendingIconStyleProperty =
|
public static readonly BindableProperty DescendingIconStyleProperty =
|
||||||
BindableProperty.Create(nameof(DescendingIconStyle), typeof(Style), typeof(DataGrid), null,
|
BindableProperty.Create(nameof(DescendingIconStyle), typeof(Style), typeof(DataGrid), null,
|
||||||
|
|
||||||
propertyChanged: (b, o, n) =>
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
var style = (n as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty);
|
var style = (newValue as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty);
|
||||||
if (style != null)
|
if (style != null)
|
||||||
{
|
{
|
||||||
if (style.Value is string vs)
|
if (style.Value is string vs)
|
||||||
@ -244,19 +397,19 @@ namespace Aurora.Design.Components.DataGrid
|
|||||||
|
|
||||||
public static readonly BindableProperty AscendingIconStyleProperty =
|
public static readonly BindableProperty AscendingIconStyleProperty =
|
||||||
BindableProperty.Create(nameof(AscendingIconStyle), typeof(Style), typeof(DataGrid), null,
|
BindableProperty.Create(nameof(AscendingIconStyle), typeof(Style), typeof(DataGrid), null,
|
||||||
coerceValue: (b, v) =>
|
coerceValue: (bindable, v) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
},
|
},
|
||||||
|
|
||||||
propertyChanged: (b, o, n) =>
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
var self = b as DataGrid;
|
var self = bindable as DataGrid;
|
||||||
if ((n as Style).Setters.Any(x => x.Property == Image.SourceProperty))
|
if ((newValue as Style).Setters.Any(x => x.Property == Image.SourceProperty))
|
||||||
{
|
{
|
||||||
var style = (n as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty);
|
var style = (newValue as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty);
|
||||||
if (style != null)
|
if (style != null)
|
||||||
{
|
{
|
||||||
if (style.Value is string vs)
|
if (style.Value is string vs)
|
||||||
@ -269,10 +422,10 @@ namespace Aurora.Design.Components.DataGrid
|
|||||||
|
|
||||||
public static readonly BindableProperty NoDataViewProperty =
|
public static readonly BindableProperty NoDataViewProperty =
|
||||||
BindableProperty.Create(nameof(NoDataView), typeof(View), typeof(DataGrid),
|
BindableProperty.Create(nameof(NoDataView), typeof(View), typeof(DataGrid),
|
||||||
propertyChanged: (b, o, n) =>
|
propertyChanged: (bindable, oldValue, newValue) =>
|
||||||
{
|
{
|
||||||
if (o != n)
|
if (oldValue != newValue)
|
||||||
(b as DataGrid)._noDataView.Content = n as View;
|
(bindable as DataGrid)._noDataView.Content = newValue as View;
|
||||||
});
|
});
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -319,19 +472,20 @@ namespace Aurora.Design.Components.DataGrid
|
|||||||
set { SetValue(ItemsSourceProperty, value); }
|
set { SetValue(ItemsSourceProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
IList<object> _internalItems;
|
internal ObservableCollection<object> InternalItems
|
||||||
|
|
||||||
internal IList<object> InternalItems
|
|
||||||
{
|
{
|
||||||
get { return _internalItems; }
|
get { return _internalItems; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_internalItems = value;
|
if (value != _internalItems)
|
||||||
|
{
|
||||||
if (IsSortable && SortedColumnIndex != null)
|
_internalItems = value;
|
||||||
SortItems(SortedColumnIndex);
|
if (IsSortable && SortedColumnIndex != null)
|
||||||
else
|
{
|
||||||
_listView.ItemsSource = _internalItems;
|
SortItems(SortedColumnIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataList.ItemsSource = _internalItems;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,51 +610,6 @@ namespace Aurora.Design.Components.DataGrid
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Fields
|
|
||||||
Dictionary<int, SortingOrder> _sortingOrders;
|
|
||||||
ListView _listView;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ctor
|
|
||||||
|
|
||||||
public DataGrid() : this(ListViewCachingStrategy.RecycleElement)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataGrid(ListViewCachingStrategy cachingStrategy)
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
_sortingOrders = new Dictionary<int, SortingOrder>();
|
|
||||||
|
|
||||||
_listView = new ListView(cachingStrategy)
|
|
||||||
{
|
|
||||||
BackgroundColor = Color.FromHex("#222222"),
|
|
||||||
ItemTemplate = new DataGridRowTemplateSelector(),
|
|
||||||
};
|
|
||||||
BackgroundColor = Color.Transparent;
|
|
||||||
|
|
||||||
_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
|
#region UI Methods
|
||||||
protected override void OnParentSet()
|
protected override void OnParentSet()
|
||||||
{
|
{
|
||||||
@ -514,13 +623,64 @@ namespace Aurora.Design.Components.DataGrid
|
|||||||
SetColumnsBindingContext();
|
SetColumnsBindingContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Reload()
|
|
||||||
{
|
|
||||||
InternalItems = new List<object>(_internalItems);
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Header Creation Methods
|
#region Private Methods
|
||||||
|
|
||||||
|
private void Reload()
|
||||||
|
{
|
||||||
|
InternalItems = new ObservableCollection<object>(_internalItems);
|
||||||
|
}
|
||||||
|
private void SortItems(SortData sData)
|
||||||
|
{
|
||||||
|
if (InternalItems == null || sData.Index >= Columns.Count || !Columns[sData.Index].SortingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var items = InternalItems;
|
||||||
|
var column = Columns[sData.Index];
|
||||||
|
SortingOrder order = sData.Order;
|
||||||
|
|
||||||
|
if (!IsSortable)
|
||||||
|
throw new InvalidOperationException("This DataGrid is not sortable");
|
||||||
|
else if (column.PropertyName == null)
|
||||||
|
throw new InvalidOperationException("Please set the PropertyName property of Column");
|
||||||
|
|
||||||
|
//Sort
|
||||||
|
// if (order == SortingOrder.Descendant)
|
||||||
|
// items = items.OrderByDescending(x => ReflectionUtils.GetValueByPath(x, column.PropertyName)).ToList();
|
||||||
|
// else
|
||||||
|
// items = items.OrderBy(x => ReflectionUtils.GetValueByPath(x, column.PropertyName)).ToList();
|
||||||
|
|
||||||
|
column.SortingIcon.Style = (order == SortingOrder.Descendant) ?
|
||||||
|
AscendingIconStyle ?? (Style)_headerView.Resources["DescendingIconStyle"] :
|
||||||
|
DescendingIconStyle ?? (Style)_headerView.Resources["AscendingIconStyle"];
|
||||||
|
|
||||||
|
//Support DescendingIcon property (if setted)
|
||||||
|
if (!column.SortingIcon.Style.Setters.Any(x => x.Property == Image.SourceProperty))
|
||||||
|
{
|
||||||
|
if (order == SortingOrder.Descendant && DescendingIconProperty.DefaultValue != DescendingIcon)
|
||||||
|
column.SortingIcon.Source = DescendingIcon;
|
||||||
|
if (order == SortingOrder.Ascendant && AscendingIconProperty.DefaultValue != AscendingIcon)
|
||||||
|
column.SortingIcon.Source = AscendingIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Columns.Count; i++)
|
||||||
|
{
|
||||||
|
if (i != sData.Index)
|
||||||
|
{
|
||||||
|
if (Columns[i].SortingIcon.Style != null)
|
||||||
|
Columns[i].SortingIcon.Style = null;
|
||||||
|
if (Columns[i].SortingIcon.Source != null)
|
||||||
|
Columns[i].SortingIcon.Source = null;
|
||||||
|
_sortingOrders[i] = SortingOrder.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_internalItems = items;
|
||||||
|
|
||||||
|
_sortingOrders[sData.Index] = order;
|
||||||
|
SortedColumnIndex = sData;
|
||||||
|
}
|
||||||
|
|
||||||
private View GetHeaderViewForColumn(DataGridColumn column)
|
private View GetHeaderViewForColumn(DataGridColumn column)
|
||||||
{
|
{
|
||||||
@ -590,61 +750,7 @@ namespace Aurora.Design.Components.DataGrid
|
|||||||
foreach (var c in Columns)
|
foreach (var c in Columns)
|
||||||
c.BindingContext = BindingContext;
|
c.BindingContext = BindingContext;
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Sorting methods
|
#endregion Private 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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
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:ml="clr-namespace:Aurora.Design.Components.MemberList"
|
xmlns:ml="clr-namespace:Aurora.Design.Components.MemberList"
|
||||||
|
xmlns:dg="clr-namespace:Aurora.Design.Components.DataGrid"
|
||||||
xmlns:library="clr-namespace:Aurora.Design.Components.Library"
|
xmlns:library="clr-namespace:Aurora.Design.Components.Library"
|
||||||
x:Class="Aurora.Design.Views.Party.PartyView">
|
x:Class="Aurora.Design.Views.Party.PartyView">
|
||||||
<ContentView.Content>
|
<ContentView.Content>
|
||||||
@ -11,7 +12,7 @@
|
|||||||
<RowDefinition
|
<RowDefinition
|
||||||
Height="*"/>
|
Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<!-- <StackLayout
|
<StackLayout
|
||||||
Grid.Row="0">
|
Grid.Row="0">
|
||||||
<Label
|
<Label
|
||||||
Text="Party Members"/>
|
Text="Party Members"/>
|
||||||
@ -20,13 +21,97 @@
|
|||||||
Members="{Binding Members}"/>
|
Members="{Binding Members}"/>
|
||||||
<Label
|
<Label
|
||||||
Text="Queue"/>
|
Text="Queue"/>
|
||||||
|
<dg:DataGrid
|
||||||
</StackLayout> -->
|
x:Name="LibraryDataGrid"
|
||||||
<library:Library
|
SelectionEnabled="True"
|
||||||
Grid.Row="1"
|
RowHeight="30"
|
||||||
|
BorderColor="#3a3a3a"
|
||||||
|
BorderThickness="0"
|
||||||
|
HeaderHeight="40"
|
||||||
|
HeaderBackground="#222222"
|
||||||
|
ItemsSource="{Binding Queue}">
|
||||||
|
<dg:DataGrid.HeaderLabelStyle>
|
||||||
|
<Style
|
||||||
|
TargetType="Label">
|
||||||
|
<Setter
|
||||||
|
Property="HorizontalOptions"
|
||||||
|
Value="Start"/>
|
||||||
|
<Setter
|
||||||
|
Property="FontSize"
|
||||||
|
Value="14"/>
|
||||||
|
<Setter
|
||||||
|
Property="TextColor"
|
||||||
|
Value="White"/>
|
||||||
|
</Style>
|
||||||
|
</dg:DataGrid.HeaderLabelStyle>
|
||||||
|
<dg:DataGrid.GestureRecognizers>
|
||||||
|
<TapGestureRecognizer
|
||||||
|
NumberOfTapsRequired="2"/>
|
||||||
|
</dg:DataGrid.GestureRecognizers>
|
||||||
|
<dg:DataGrid.Columns>
|
||||||
|
<dg:DataGridColumn
|
||||||
|
Title=""
|
||||||
|
PropertyName="Icon"
|
||||||
|
Width="15">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Image
|
||||||
|
Source="../../Resources/unselected.png"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
<dg:DataGridColumn
|
||||||
|
Title="Title"
|
||||||
|
PropertyName="Metadata.Title"
|
||||||
|
Width="2*">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Text="{Binding .}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
<dg:DataGridColumn
|
||||||
|
Title="Album"
|
||||||
|
PropertyName="Metadata.Album"
|
||||||
|
Width="0.95*">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Text="{Binding .}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
<dg:DataGridColumn
|
||||||
|
Title="Artist"
|
||||||
|
PropertyName="Metadata.Artist"
|
||||||
|
Width="1*">
|
||||||
|
<dg:DataGridColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Text="{Binding .}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</dg:DataGridColumn.CellTemplate>
|
||||||
|
</dg:DataGridColumn>
|
||||||
|
</dg:DataGrid.Columns>
|
||||||
|
<dg:DataGrid.RowsTextColorPalette>
|
||||||
|
<dg:PaletteCollection>
|
||||||
|
<Color>White</Color>
|
||||||
|
</dg:PaletteCollection>
|
||||||
|
</dg:DataGrid.RowsTextColorPalette>
|
||||||
|
<dg:DataGrid.RowsBackgroundColorPalette>
|
||||||
|
<dg:PaletteCollection>
|
||||||
|
<Color>Transparent</Color>
|
||||||
|
</dg:PaletteCollection>
|
||||||
|
</dg:DataGrid.RowsBackgroundColorPalette>
|
||||||
|
</dg:DataGrid><!-- <library:Library
|
||||||
ItemsSource="{Binding Queue}"
|
ItemsSource="{Binding Queue}"
|
||||||
SelectedItem="{Binding SelectedSong}"
|
SelectedItem="{Binding SelectedSong}"
|
||||||
ItemDoubleClicked="{Binding PlayCommand}"/>
|
ItemDoubleClicked="{Binding PlayCommand}"/> -->
|
||||||
|
</StackLayout>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ContentView.Content>
|
</ContentView.Content>
|
||||||
</ContentView>
|
</ContentView>
|
Loading…
Reference in New Issue
Block a user