Kaynağa Gözat

avalonia: Added ability to style DataGrid rows and fixed DataGrid selection

Kenric Nugteren 3 hafta önce
ebeveyn
işleme
1ce43b306d

+ 1 - 2
InABox.Avalonia/Components/AvaloniaDataGrid/AvaloniaDataGrid.axaml

@@ -36,14 +36,13 @@
 					  RowBackground="White"
 					  Foreground="Black"
 					  AutoGenerateColumns="False"
-					  SelectionMode="{Binding $parent[components:AvaloniaDataGrid].SelectionMode}"
 					  Tapped="DataGrid_Tapped"
 					  SelectionChanged="DataGrid_SelectionChanged"
 					  RowHeight="{Binding $parent[components:AvaloniaDataGrid].RowHeight}"
 					  GridLinesVisibility="Vertical"
 					  FontSize="{StaticResource PrsFontSizeSmall}"
 					  CornerRadius="{StaticResource PrsCornerRadius}"
-					  >
+					  LoadingRow="DataGrid_LoadingRow">
 				<DataGrid.Styles>
 					<Style Selector="DataGridRow:nth-child(even)">
 						<Setter Property="Background" Value="WhiteSmoke"/>

+ 54 - 6
InABox.Avalonia/Components/AvaloniaDataGrid/AvaloniaDataGrid.axaml.cs

@@ -2,9 +2,12 @@ using Avalonia;
 using Avalonia.Collections;
 using Avalonia.Controls;
 using Avalonia.Controls.Primitives;
+using Avalonia.Data;
+using Avalonia.Data.Converters;
 using Avalonia.Input;
 using Avalonia.Markup.Xaml;
 using Avalonia.Media;
+using Avalonia.Styling;
 using Avalonia.VisualTree;
 using CommunityToolkit.Mvvm.Input;
 using InABox.Core;
@@ -21,6 +24,13 @@ public class AvaloniaDataGridRefreshRequestedEventArgs()
 {
 }
 
+public enum AvaloniaDataGridSelectionMode
+{
+    None,
+    Single,
+    Multiple
+}
+
 public partial class AvaloniaDataGrid : UserControl, INotifyPropertyChanged
 {
     public static StyledProperty<bool> CanSearchProperty =
@@ -33,8 +43,8 @@ public partial class AvaloniaDataGrid : UserControl, INotifyPropertyChanged
         AvaloniaProperty.Register<AvaloniaDataGrid, bool>(nameof(ShowRecordCount));
     public static StyledProperty<bool> RefreshVisibleProperty =
         AvaloniaProperty.Register<AvaloniaDataGrid, bool>(nameof(RefreshVisible));
-    public static StyledProperty<SelectionMode> SelectionModeProperty =
-        AvaloniaProperty.Register<AvaloniaDataGrid, SelectionMode>(nameof(SelectionMode), SelectionMode.Single);
+    public static StyledProperty<AvaloniaDataGridSelectionMode> SelectionModeProperty =
+        AvaloniaProperty.Register<AvaloniaDataGrid, AvaloniaDataGridSelectionMode>(nameof(SelectionMode), AvaloniaDataGridSelectionMode.Single);
     public static StyledProperty<double> RowHeightProperty =
         AvaloniaProperty.Register<AvaloniaDataGrid, double>(nameof(RowHeight), 30);
 
@@ -63,7 +73,7 @@ public partial class AvaloniaDataGrid : UserControl, INotifyPropertyChanged
         get => GetValue(RefreshVisibleProperty);
         set => SetValue(RefreshVisibleProperty, value);
     }
-    public SelectionMode SelectionMode
+    public AvaloniaDataGridSelectionMode SelectionMode
     {
         get => GetValue(SelectionModeProperty);
         set => SetValue(SelectionModeProperty, value);
@@ -88,6 +98,9 @@ public partial class AvaloniaDataGrid : UserControl, INotifyPropertyChanged
 
     public event EventHandler<AvaloniaDataGridSelectionChangedEventArgs>? SelectionChanged;
     public event EventHandler<AvaloniaDataGridRefreshRequestedEventArgs>? RefreshRequested;
+    public event Predicate<object?>? FilterRow;
+
+    public event EventHandler<DataGridRowEventArgs>? LoadingRow;
 
     #region Static Constructor and Property Changed Handlers
 
@@ -139,6 +152,21 @@ public partial class AvaloniaDataGrid : UserControl, INotifyPropertyChanged
 
         Columns = new AvaloniaDataGridColumns();
         Columns.Changed += Columns_Changed;
+
+        Grid.Bind(DataGrid.SelectionModeProperty, new Binding(nameof(SelectionMode))
+        {
+            Source = this,
+            Converter = new FuncValueConverter<AvaloniaDataGridSelectionMode, DataGridSelectionMode>(x => x switch
+            {
+                AvaloniaDataGridSelectionMode.Multiple => DataGridSelectionMode.Extended,
+                AvaloniaDataGridSelectionMode.Single or AvaloniaDataGridSelectionMode.None or _ => DataGridSelectionMode.Single,
+            })
+        });
+    }
+
+    private void DataGrid_LoadingRow(object? sender, DataGridRowEventArgs e)
+    {
+        LoadingRow?.Invoke(this, e);
     }
 
     private void CollectionView_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
@@ -190,11 +218,24 @@ public partial class AvaloniaDataGrid : UserControl, INotifyPropertyChanged
         return false;
     }
 
+    private bool DoFilter(object? item)
+    {
+        return DoSearch(item) && (FilterRow is null || FilterRow(item));
+    }
+
+    public void InvalidateGrid()
+    {
+        if (Grid.CollectionView is null) return;
+        Grid.CollectionView.Filter = DoFilter;
+        Grid.CollectionView.Refresh();
+        UpdateSummaryRow();
+    }
+
     [RelayCommand]
     private void Search()
     {
         if (Grid.CollectionView is null) return;
-        Grid.CollectionView.Filter = DoSearch;
+        Grid.CollectionView.Filter = DoFilter;
         Grid.CollectionView.Refresh();
         UpdateSummaryRow();
     }
@@ -210,14 +251,21 @@ public partial class AvaloniaDataGrid : UserControl, INotifyPropertyChanged
 
     private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
     {
-        if (SelectionMode != SelectionMode.Multiple) return;
+        if(SelectionMode == AvaloniaDataGridSelectionMode.None && Grid.SelectedItems.Count > 0)
+        {
+            e.Handled = true;
+            Grid.SelectedItem = null;
+            return;
+        }
+
+        if (SelectionMode != AvaloniaDataGridSelectionMode.Multiple) return;
 
         SelectionChanged?.Invoke(this, new AvaloniaDataGridSelectionChangedEventArgs(SelectedItems.ToArray()));
     }
 
     private void DataGrid_Tapped(object sender, TappedEventArgs e)
     {
-        if (SelectionMode == SelectionMode.Multiple) return;
+        if (SelectionMode == AvaloniaDataGridSelectionMode.Multiple) return;
 
         var position = e.GetPosition(Grid);