From 232980ba4b622ef2911b3ba2d4ccf933cbd2cafb Mon Sep 17 00:00:00 2001 From: John Stewien Date: Mon, 8 Feb 2021 16:25:10 +1030 Subject: [PATCH] Added a couple DataGrid grouping sorting and filtering examples for #8 --- .../App.xaml | 9 + .../App.xaml.cs | 2 +- .../AssemblyInfo.cs | 0 .../Controls/CompleteConverter.cs | 2 +- .../Controls/CustomSortBehavior.cs | 145 ++++++++ .../Controls/DataGridTestControl.xaml | 15 +- .../Controls/DataGridTestControl.xaml.cs | 4 +- .../Controls/ProjectDetailsSorter.cs | 68 ++++ ...DGGroupSortFilterExampleConcurrent.csproj} | 5 +- .../MainWindow.xaml | 4 +- .../MainWindow.xaml.cs | 4 +- .../ViewModels/DataGridTestViewModel.cs | 2 +- .../ViewModels/ProjectDetails.cs | 2 +- .../ViewModels/RelayCommand.cs | 2 +- .../App.xaml | 18 +- .../App.xaml.cs | 17 + .../AssemblyInfo.cs | 10 + .../DGGroupSortFilterExampleNormal.csproj | 9 + .../MainWindow.xaml | 85 +++++ .../MainWindow.xaml.cs | 216 ++++++++++++ Swordfish.NET.Collections.sln | 317 +++++++++--------- 21 files changed, 754 insertions(+), 182 deletions(-) create mode 100644 ExamplesAndTests/DGGroupSortFilterExampleConcurrent/App.xaml rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/App.xaml.cs (86%) rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/AssemblyInfo.cs (100%) rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/Controls/CompleteConverter.cs (95%) create mode 100644 ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/CustomSortBehavior.cs rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/Controls/DataGridTestControl.xaml (90%) rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/Controls/DataGridTestControl.xaml.cs (95%) create mode 100644 ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/ProjectDetailsSorter.cs rename ExamplesAndTests/{DGGroupSortFilterExample/DGGroupSortFilterExample.csproj => DGGroupSortFilterExampleConcurrent/DGGroupSortFilterExampleConcurrent.csproj} (91%) rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/MainWindow.xaml (75%) rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/MainWindow.xaml.cs (86%) rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/ViewModels/DataGridTestViewModel.cs (98%) rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/ViewModels/ProjectDetails.cs (98%) rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleConcurrent}/ViewModels/RelayCommand.cs (99%) rename ExamplesAndTests/{DGGroupSortFilterExample => DGGroupSortFilterExampleNormal}/App.xaml (67%) create mode 100644 ExamplesAndTests/DGGroupSortFilterExampleNormal/App.xaml.cs create mode 100644 ExamplesAndTests/DGGroupSortFilterExampleNormal/AssemblyInfo.cs create mode 100644 ExamplesAndTests/DGGroupSortFilterExampleNormal/DGGroupSortFilterExampleNormal.csproj create mode 100644 ExamplesAndTests/DGGroupSortFilterExampleNormal/MainWindow.xaml create mode 100644 ExamplesAndTests/DGGroupSortFilterExampleNormal/MainWindow.xaml.cs diff --git a/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/App.xaml b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/App.xaml new file mode 100644 index 0000000..fa7ea38 --- /dev/null +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/ExamplesAndTests/DGGroupSortFilterExample/App.xaml.cs b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/App.xaml.cs similarity index 86% rename from ExamplesAndTests/DGGroupSortFilterExample/App.xaml.cs rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/App.xaml.cs index b337cc1..2f94c9f 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/App.xaml.cs +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/App.xaml.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using System.Windows; -namespace EditableDataGridTest +namespace DGGroupSortFilterExampleConcurrent { /// /// Interaction logic for App.xaml diff --git a/ExamplesAndTests/DGGroupSortFilterExample/AssemblyInfo.cs b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/AssemblyInfo.cs similarity index 100% rename from ExamplesAndTests/DGGroupSortFilterExample/AssemblyInfo.cs rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/AssemblyInfo.cs diff --git a/ExamplesAndTests/DGGroupSortFilterExample/Controls/CompleteConverter.cs b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/CompleteConverter.cs similarity index 95% rename from ExamplesAndTests/DGGroupSortFilterExample/Controls/CompleteConverter.cs rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/CompleteConverter.cs index 1f775f2..786c430 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/Controls/CompleteConverter.cs +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/CompleteConverter.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using System.Windows.Data; -namespace DGGroupSortFilterExample.Controls +namespace DGGroupSortFilterExampleConcurrent.Controls { [ValueConversion(typeof(Boolean), typeof(String))] public class CompleteConverter : IValueConverter diff --git a/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/CustomSortBehavior.cs b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/CustomSortBehavior.cs new file mode 100644 index 0000000..38d3db8 --- /dev/null +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/CustomSortBehavior.cs @@ -0,0 +1,145 @@ +// from https://stackoverflow.com/questions/18122751/wpf-datagrid-customsort-for-each-column/18218963 + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; + +namespace DGGroupSortFilterExampleConcurrent.Controls +{ + /// + /// Optional behavior for doing custom sorting + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public class CustomSortBehavior + { + #region Fields and Constants + + public static readonly DependencyProperty CustomSorterProperty = + DependencyProperty.RegisterAttached("CustomSorter", typeof(ICustomSorter), typeof(CustomSortBehavior)); + + public static readonly DependencyProperty AllowCustomSortProperty = + DependencyProperty.RegisterAttached("AllowCustomSort", + typeof(bool), + typeof(CustomSortBehavior), + new UIPropertyMetadata(false, OnAllowCustomSortChanged)); + + #endregion + + #region public Methods + + public static bool GetAllowCustomSort(DataGrid grid) + { + return (bool)grid.GetValue(AllowCustomSortProperty); + } + + + public static ICustomSorter GetCustomSorter(DataGrid grid) + { + return (ICustomSorter)grid.GetValue(CustomSorterProperty); + } + + public static void SetAllowCustomSort(DataGrid grid, bool value) + { + grid.SetValue(AllowCustomSortProperty, value); + } + + + public static void SetCustomSorter(DataGrid grid, ICustomSorter value) + { + grid.SetValue(CustomSorterProperty, value); + } + + #endregion + + #region nonpublic Methods + + private static void HandleCustomSorting(object sender, DataGridSortingEventArgs e) + { + var dataGrid = sender as DataGrid; + if (dataGrid == null || !GetAllowCustomSort(dataGrid)) + { + return; + } + + var listColView = dataGrid.ItemsSource as ListCollectionView; + if (listColView == null) + { + throw new Exception("The DataGrid's ItemsSource property must be of type, ListCollectionView"); + } + + // Sanity check + var sorter = GetCustomSorter(dataGrid); + if (sorter == null) + { + return; + } + + // The guts. + e.Handled = true; + + var direction = (e.Column.SortDirection != ListSortDirection.Ascending) + ? ListSortDirection.Ascending + : ListSortDirection.Descending; + + e.Column.SortDirection = sorter.SortDirection = direction; + sorter.SortMemberPath = e.Column.SortMemberPath; + + listColView.CustomSort = sorter; + } + + private static void OnAllowCustomSortChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var existing = d as DataGrid; + if (existing == null) + { + return; + } + + var oldAllow = (bool)e.OldValue; + var newAllow = (bool)e.NewValue; + + if (!oldAllow && newAllow) + { + existing.Sorting += HandleCustomSorting; + } + else + { + existing.Sorting -= HandleCustomSorting; + } + } + + #endregion + } + + public interface ICustomSorter : IComparer + { + ListSortDirection SortDirection { get; set; } + + string SortMemberPath { get; set; } + } + +} diff --git a/ExamplesAndTests/DGGroupSortFilterExample/Controls/DataGridTestControl.xaml b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/DataGridTestControl.xaml similarity index 90% rename from ExamplesAndTests/DGGroupSortFilterExample/Controls/DataGridTestControl.xaml rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/DataGridTestControl.xaml index 8039f84..3244736 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/Controls/DataGridTestControl.xaml +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/DataGridTestControl.xaml @@ -1,21 +1,16 @@ - + - - - - - - + @@ -28,6 +23,8 @@ /// Interaction logic for DataGridTestControl.xaml diff --git a/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/ProjectDetailsSorter.cs b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/ProjectDetailsSorter.cs new file mode 100644 index 0000000..3cba847 --- /dev/null +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/Controls/ProjectDetailsSorter.cs @@ -0,0 +1,68 @@ +using DGGroupSortFilterExampleConcurrent.ViewModels; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DGGroupSortFilterExampleConcurrent.Controls +{ + /// + /// An optimised sorter for use with ProjectDetails objects + /// + public class ProjectDetailsSorter : ICustomSorter + { + private Func _comparer = (x, y) => 0; + + private void UpdateComparer() + { + int upDown = SortDirection == ListSortDirection.Ascending ? 1 : -1; + + Func selector = SortMemberPath switch + { + nameof(ProjectDetails.ProjectName) => (x, y) => upDown * Comparer.Default.Compare(x.ProjectName, y.ProjectName), + nameof(ProjectDetails.Complete) => (x, y) => upDown * Comparer.Default.Compare(x.Complete, y.Complete), + nameof(ProjectDetails.DueDate) => (x, y) => upDown * Comparer.Default.Compare(x.DueDate, y.DueDate), + nameof(ProjectDetails.TaskName) => (x, y) => upDown * Comparer.Default.Compare(x.TaskName, y.TaskName), + _ => (x, y) => 0 + }; + + _comparer = (a, b) => + { + if (a is ProjectDetails x && b is ProjectDetails y) + { + return selector(x, y); + } + else + { + return 0; + } + }; + } + + private ListSortDirection _listSortDirection = ListSortDirection.Ascending; + public ListSortDirection SortDirection + { + get => _listSortDirection; + set + { + _listSortDirection = value; + UpdateComparer(); + } + } + + private string _sortMemberPath = string.Empty; + public string SortMemberPath + { + get => _sortMemberPath; + set + { + _sortMemberPath = value; + UpdateComparer(); + } + } + + public int Compare(object x, object y) => _comparer(x, y); + } +} diff --git a/ExamplesAndTests/DGGroupSortFilterExample/DGGroupSortFilterExample.csproj b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/DGGroupSortFilterExampleConcurrent.csproj similarity index 91% rename from ExamplesAndTests/DGGroupSortFilterExample/DGGroupSortFilterExample.csproj rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/DGGroupSortFilterExampleConcurrent.csproj index 5994e52..5cac7e8 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/DGGroupSortFilterExample.csproj +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/DGGroupSortFilterExampleConcurrent.csproj @@ -4,14 +4,15 @@ WinExe net461 true + preview - - + + \ No newline at end of file diff --git a/ExamplesAndTests/DGGroupSortFilterExample/MainWindow.xaml b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/MainWindow.xaml similarity index 75% rename from ExamplesAndTests/DGGroupSortFilterExample/MainWindow.xaml rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/MainWindow.xaml index 21a8da2..5f6a2c0 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/MainWindow.xaml +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/MainWindow.xaml @@ -1,9 +1,9 @@ - diff --git a/ExamplesAndTests/DGGroupSortFilterExample/MainWindow.xaml.cs b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/MainWindow.xaml.cs similarity index 86% rename from ExamplesAndTests/DGGroupSortFilterExample/MainWindow.xaml.cs rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/MainWindow.xaml.cs index 12e4b4f..a697447 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/MainWindow.xaml.cs +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/MainWindow.xaml.cs @@ -1,4 +1,4 @@ -using DGGroupSortFilterExample.ViewModels; +using DGGroupSortFilterExampleConcurrent.ViewModels; using System; using System.Collections.Generic; using System.Linq; @@ -14,7 +14,7 @@ using System.Windows.Navigation; using System.Windows.Shapes; -namespace DGGroupSortFilterExample +namespace DGGroupSortFilterExampleConcurrent { /// /// Interaction logic for MainWindow.xaml diff --git a/ExamplesAndTests/DGGroupSortFilterExample/ViewModels/DataGridTestViewModel.cs b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/ViewModels/DataGridTestViewModel.cs similarity index 98% rename from ExamplesAndTests/DGGroupSortFilterExample/ViewModels/DataGridTestViewModel.cs rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/ViewModels/DataGridTestViewModel.cs index a3fde04..65cd49d 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/ViewModels/DataGridTestViewModel.cs +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/ViewModels/DataGridTestViewModel.cs @@ -9,7 +9,7 @@ using System.Windows.Input; using System.Windows.Media.Animation; -namespace DGGroupSortFilterExample.ViewModels +namespace DGGroupSortFilterExampleConcurrent.ViewModels { /// /// View model used as a source of items for both a ListView and a DataGrid diff --git a/ExamplesAndTests/DGGroupSortFilterExample/ViewModels/ProjectDetails.cs b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/ViewModels/ProjectDetails.cs similarity index 98% rename from ExamplesAndTests/DGGroupSortFilterExample/ViewModels/ProjectDetails.cs rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/ViewModels/ProjectDetails.cs index f9423e2..5f4a2b9 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/ViewModels/ProjectDetails.cs +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/ViewModels/ProjectDetails.cs @@ -7,7 +7,7 @@ using System.Threading; using System.Threading.Tasks; -namespace DGGroupSortFilterExample.ViewModels +namespace DGGroupSortFilterExampleConcurrent.ViewModels { // Task Class // Requires using System.ComponentModel; diff --git a/ExamplesAndTests/DGGroupSortFilterExample/ViewModels/RelayCommand.cs b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/ViewModels/RelayCommand.cs similarity index 99% rename from ExamplesAndTests/DGGroupSortFilterExample/ViewModels/RelayCommand.cs rename to ExamplesAndTests/DGGroupSortFilterExampleConcurrent/ViewModels/RelayCommand.cs index c33a8a4..d71d62a 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/ViewModels/RelayCommand.cs +++ b/ExamplesAndTests/DGGroupSortFilterExampleConcurrent/ViewModels/RelayCommand.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using System.Windows.Input; -namespace DGGroupSortFilterExample.ViewModels +namespace DGGroupSortFilterExampleConcurrent.ViewModels { /// /// Preferable to use RelayCommandFactory to generate these diff --git a/ExamplesAndTests/DGGroupSortFilterExample/App.xaml b/ExamplesAndTests/DGGroupSortFilterExampleNormal/App.xaml similarity index 67% rename from ExamplesAndTests/DGGroupSortFilterExample/App.xaml rename to ExamplesAndTests/DGGroupSortFilterExampleNormal/App.xaml index 4e47c4b..f7d3355 100644 --- a/ExamplesAndTests/DGGroupSortFilterExample/App.xaml +++ b/ExamplesAndTests/DGGroupSortFilterExampleNormal/App.xaml @@ -1,9 +1,9 @@ - - - - - + + + + + diff --git a/ExamplesAndTests/DGGroupSortFilterExampleNormal/App.xaml.cs b/ExamplesAndTests/DGGroupSortFilterExampleNormal/App.xaml.cs new file mode 100644 index 0000000..2e23d10 --- /dev/null +++ b/ExamplesAndTests/DGGroupSortFilterExampleNormal/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace DGGroupSortFilterExample +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/ExamplesAndTests/DGGroupSortFilterExampleNormal/AssemblyInfo.cs b/ExamplesAndTests/DGGroupSortFilterExampleNormal/AssemblyInfo.cs new file mode 100644 index 0000000..74087a1 --- /dev/null +++ b/ExamplesAndTests/DGGroupSortFilterExampleNormal/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/ExamplesAndTests/DGGroupSortFilterExampleNormal/DGGroupSortFilterExampleNormal.csproj b/ExamplesAndTests/DGGroupSortFilterExampleNormal/DGGroupSortFilterExampleNormal.csproj new file mode 100644 index 0000000..a5efc16 --- /dev/null +++ b/ExamplesAndTests/DGGroupSortFilterExampleNormal/DGGroupSortFilterExampleNormal.csproj @@ -0,0 +1,9 @@ + + + + WinExe + net461 + true + + + diff --git a/ExamplesAndTests/DGGroupSortFilterExampleNormal/MainWindow.xaml b/ExamplesAndTests/DGGroupSortFilterExampleNormal/MainWindow.xaml new file mode 100644 index 0000000..456f550 --- /dev/null +++ b/ExamplesAndTests/DGGroupSortFilterExampleNormal/MainWindow.xaml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +