Skip to content

Commit

Permalink
Added a couple DataGrid grouping sorting and filtering examples for #8
Browse files Browse the repository at this point in the history
  • Loading branch information
stewienj committed Feb 8, 2021
1 parent eb7655b commit 232980b
Show file tree
Hide file tree
Showing 21 changed files with 754 additions and 182 deletions.
9 changes: 9 additions & 0 deletions ExamplesAndTests/DGGroupSortFilterExampleConcurrent/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Application x:Class="DGGroupSortFilterExampleConcurrent.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DGGroupSortFilterExampleConcurrent"
StartupUri="MainWindow.xaml">
<Application.Resources>

</Application.Resources>
</Application>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Threading.Tasks;
using System.Windows;

namespace EditableDataGridTest
namespace DGGroupSortFilterExampleConcurrent
{
/// <summary>
/// Interaction logic for App.xaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Optional behavior for doing custom sorting
/// </summary>
/// <example>
/// <Window.Resources>
/// <local:CustomSorter x:Key="MySorter"/>
/// </Window.Resources>
///
/// <Grid>
/// <DataGrid ItemsSource = "{Binding ...}"
/// local:CustomSortBehavior.CustomSorter =
/// local:CustomSortBehavior.AllowCustomSort="True"
/// <DataGrid.Columns>
/// <DataGridTextColumn Header = "Column 1" Binding="{Binding Column1}"/>
/// <DataGridTextColumn Header = "Column 2" Binding="{Binding Column2}"/>
/// <DataGridTextColumn Header = "Column 3" Binding="{Binding Column3}"/>
/// </DataGrid.Columns>
/// </DataGrid>
/// </Grid>
/// </Window>
/// </example>
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; }
}

}
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
<UserControl x:Class="DGGroupSortFilterExample.Controls.DataGridTestControl"
<UserControl x:Class="DGGroupSortFilterExampleConcurrent.Controls.DataGridTestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DGGroupSortFilterExample.Controls"
xmlns:local="clr-namespace:DGGroupSortFilterExampleConcurrent.Controls"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<local:ProjectDetailsSorter x:Key="MySorter"/>
<local:CompleteConverter x:Key="completeConverter" />
<CollectionViewSource x:Key="cvsTasks" Source="{Binding EditableProjectList}"
Filter="CollectionViewSource_Filter">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="ProjectName"/>
<scm:SortDescription PropertyName="Complete" />
<scm:SortDescription PropertyName="DueDate" />
</CollectionViewSource.SortDescriptions>
<CollectionViewSource x:Key="cvsTasks" Source="{Binding EditableProjectList}" Filter="CollectionViewSource_Filter">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="ProjectName"/>
<PropertyGroupDescription PropertyName="Complete"/>
Expand All @@ -28,6 +23,8 @@
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<DataGrid x:Name="dataGrid1"
local:CustomSortBehavior.CustomSorter="{StaticResource ResourceKey=MySorter}"
local:CustomSortBehavior.AllowCustomSort="True"
ItemsSource="{Binding Source={StaticResource cvsTasks}}"
CanUserAddRows="False"
VirtualizingPanel.IsVirtualizing="True"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DGGroupSortFilterExample.ViewModels;
using DGGroupSortFilterExampleConcurrent.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
Expand All @@ -17,7 +17,7 @@
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DGGroupSortFilterExample.Controls
namespace DGGroupSortFilterExampleConcurrent.Controls
{
/// <summary>
/// Interaction logic for DataGridTestControl.xaml
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// An optimised sorter for use with ProjectDetails objects
/// </summary>
public class ProjectDetailsSorter : ICustomSorter
{
private Func<object, object, int> _comparer = (x, y) => 0;

private void UpdateComparer()
{
int upDown = SortDirection == ListSortDirection.Ascending ? 1 : -1;

Func<ProjectDetails, ProjectDetails, int> selector = SortMemberPath switch
{
nameof(ProjectDetails.ProjectName) => (x, y) => upDown * Comparer<string>.Default.Compare(x.ProjectName, y.ProjectName),
nameof(ProjectDetails.Complete) => (x, y) => upDown * Comparer<bool>.Default.Compare(x.Complete, y.Complete),
nameof(ProjectDetails.DueDate) => (x, y) => upDown * Comparer<DateTime>.Default.Compare(x.DueDate, y.DueDate),
nameof(ProjectDetails.TaskName) => (x, y) => upDown * Comparer<string>.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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
<OutputType>WinExe</OutputType>
<TargetFramework>net461</TargetFramework>
<UseWPF>true</UseWPF>
<LangVersion>preview</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.31" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Swordfish.NET.CollectionsV3\Swordfish.NET.CollectionsV3.csproj" />
<ItemGroup>
<ProjectReference Include="..\..\Swordfish.NET.CollectionsV3\Swordfish.NET.CollectionsV3.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Window x:Class="DGGroupSortFilterExample.MainWindow"
<Window x:Class="DGGroupSortFilterExampleConcurrent.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DGGroupSortFilterExample.Controls"
xmlns:local="clr-namespace:DGGroupSortFilterExampleConcurrent.Controls"
mc:Ignorable="d"
Title="Editable DataGrid Test" Height="600" Width="640">
<Grid>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DGGroupSortFilterExample.ViewModels;
using DGGroupSortFilterExampleConcurrent.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -14,7 +14,7 @@
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DGGroupSortFilterExample
namespace DGGroupSortFilterExampleConcurrent
{
/// <summary>
/// Interaction logic for MainWindow.xaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using System.Windows.Input;
using System.Windows.Media.Animation;

namespace DGGroupSortFilterExample.ViewModels
namespace DGGroupSortFilterExampleConcurrent.ViewModels
{
/// <summary>
/// View model used as a source of items for both a ListView and a DataGrid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.Threading;
using System.Threading.Tasks;

namespace DGGroupSortFilterExample.ViewModels
namespace DGGroupSortFilterExampleConcurrent.ViewModels
{
// Task Class
// Requires using System.ComponentModel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Threading.Tasks;
using System.Windows.Input;

namespace DGGroupSortFilterExample.ViewModels
namespace DGGroupSortFilterExampleConcurrent.ViewModels
{
/// <summary>
/// Preferable to use RelayCommandFactory to generate these
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Application x:Class="EditableDataGridTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:EditableDataGridTest"
StartupUri="MainWindow.xaml">
<Application.Resources>

</Application.Resources>
</Application>
<Application x:Class="DGGroupSortFilterExample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DGGroupSortFilterExample"
StartupUri="MainWindow.xaml">
<Application.Resources>

</Application.Resources>
</Application>
Loading

0 comments on commit 232980b

Please sign in to comment.