Skip to content

Commit 7fac606

Browse files
committed
Three state sort as attached property.
1 parent fa11f8d commit 7fac606

8 files changed

Lines changed: 219 additions & 0 deletions

File tree

Gu.Wpf.DataGrid2D.Demo/Gu.Wpf.DataGrid2D.Demo.csproj

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@
111111
<Compile Include="Array2DView.xaml.cs">
112112
<DependentUpon>Array2DView.xaml</DependentUpon>
113113
</Compile>
114+
<Compile Include="ThreeStateSortItem.cs">
115+
<DependentUpon>ThreeStateSortView.xaml</DependentUpon>
116+
</Compile>
117+
<Compile Include="ThreeStateSortView.xaml.cs">
118+
<DependentUpon>ThreeStateSortView.xaml</DependentUpon>
119+
</Compile>
120+
<Compile Include="ThreeStateSortViewModel.cs" />
114121
<Compile Include="TransposedView.xaml.cs">
115122
<DependentUpon>TransposedView.xaml</DependentUpon>
116123
</Compile>
@@ -166,6 +173,10 @@
166173
<SubType>Designer</SubType>
167174
<Generator>MSBuild:Compile</Generator>
168175
</Page>
176+
<Page Include="ThreeStateSortView.xaml">
177+
<SubType>Designer</SubType>
178+
<Generator>MSBuild:Compile</Generator>
179+
</Page>
169180
<Page Include="TransposedView.xaml">
170181
<SubType>Designer</SubType>
171182
<Generator>MSBuild:Compile</Generator>

Gu.Wpf.DataGrid2D.Demo/MainWindow.xaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,9 @@
4141
<TabItem AutomationProperties.AutomationId="{x:Static demo:AutomationIds.CellTemplateTab}" Header="CellTemplate">
4242
<demo:CellTemplateView />
4343
</TabItem>
44+
45+
<TabItem Header="sort">
46+
<demo:ThreeStateSortView />
47+
</TabItem>
4448
</TabControl>
4549
</Window>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
namespace Gu.Wpf.DataGrid2D.Demo
2+
{
3+
using System.ComponentModel;
4+
using System.Runtime.CompilerServices;
5+
using JetBrains.Annotations;
6+
7+
public class ThreeStateSortItem : INotifyPropertyChanged
8+
{
9+
private string stringValue;
10+
private int intValue;
11+
12+
public event PropertyChangedEventHandler PropertyChanged;
13+
14+
public string StringValue
15+
{
16+
get
17+
{
18+
return this.stringValue;
19+
}
20+
21+
set
22+
{
23+
if (value == this.stringValue)
24+
{
25+
return;
26+
}
27+
28+
this.stringValue = value;
29+
this.OnPropertyChanged();
30+
}
31+
}
32+
33+
public int IntValue
34+
{
35+
get
36+
{
37+
return this.intValue;
38+
}
39+
40+
set
41+
{
42+
if (value == this.intValue)
43+
{
44+
return;
45+
}
46+
47+
this.intValue = value;
48+
this.OnPropertyChanged();
49+
}
50+
}
51+
52+
[NotifyPropertyChangedInvocator]
53+
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
54+
{
55+
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
56+
}
57+
}
58+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<UserControl x:Class="Gu.Wpf.DataGrid2D.Demo.ThreeStateSortView"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5+
xmlns:dataGrid2D="http://gu.se/DataGrid2D"
6+
xmlns:local="clr-namespace:Gu.Wpf.DataGrid2D.Demo"
7+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
8+
d:DesignHeight="300"
9+
d:DesignWidth="300"
10+
mc:Ignorable="d">
11+
<UserControl.DataContext>
12+
<local:ThreeStateSortViewModel />
13+
</UserControl.DataContext>
14+
15+
<DataGrid dataGrid2D:Sort.ThreeState="True" ItemsSource="{Binding Items}" />
16+
</UserControl>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace Gu.Wpf.DataGrid2D.Demo
2+
{
3+
using System.Windows.Controls;
4+
5+
/// <summary>
6+
/// Interaction logic for ThreeStateSortView.xaml
7+
/// </summary>
8+
public partial class ThreeStateSortView : UserControl
9+
{
10+
public ThreeStateSortView()
11+
{
12+
this.InitializeComponent();
13+
}
14+
}
15+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace Gu.Wpf.DataGrid2D.Demo
2+
{
3+
using System.Collections.ObjectModel;
4+
5+
public class ThreeStateSortViewModel
6+
{
7+
public ThreeStateSortViewModel()
8+
{
9+
this.Items = new ObservableCollection<ThreeStateSortItem>
10+
{
11+
new ThreeStateSortItem {StringValue = "a", IntValue = 1},
12+
new ThreeStateSortItem {StringValue = "c", IntValue = 4},
13+
new ThreeStateSortItem {StringValue = "d", IntValue = 2},
14+
new ThreeStateSortItem {StringValue = "b", IntValue = 3},
15+
};
16+
}
17+
18+
public ObservableCollection<ThreeStateSortItem> Items { get; }
19+
}
20+
}

Gu.Wpf.DataGrid2D/Gu.Wpf.DataGrid2D.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
<Compile Include="ItemsSource.Array2D.cs" />
6767
<Compile Include="RowColumnIndex.cs" />
6868
<Compile Include="RowColumnIndexConverter.cs" />
69+
<Compile Include="Sort.cs" />
6970
<Compile Include="Views\Array2DRowView.cs" />
7071
<Compile Include="Views\Array2DView.cs" />
7172
<Compile Include="Views\Array2DIndexPropertyDescriptor.cs" />

Gu.Wpf.DataGrid2D/Sort.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
namespace Gu.Wpf.DataGrid2D
2+
{
3+
using System;
4+
using System.ComponentModel;
5+
using System.Windows;
6+
using System.Windows.Controls;
7+
using System.Windows.Input;
8+
9+
public class Sort
10+
{
11+
public static readonly DependencyProperty ThreeStateProperty = DependencyProperty.RegisterAttached(
12+
"ThreeState",
13+
typeof(bool),
14+
typeof(Sort),
15+
new PropertyMetadata(default(bool), OnThreeStateChanged));
16+
17+
private static readonly DependencyProperty SubscriptionProperty = DependencyProperty.RegisterAttached(
18+
"Subscription",
19+
typeof(SortingSubscription),
20+
typeof(Sort),
21+
new PropertyMetadata(default(SortingSubscription)));
22+
23+
public static void SetThreeState(DependencyObject element, bool value)
24+
{
25+
element.SetValue(ThreeStateProperty, value);
26+
}
27+
28+
public static bool GetThreeState(DependencyObject element)
29+
{
30+
return (bool)element.GetValue(ThreeStateProperty);
31+
}
32+
33+
private static void OnThreeStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
34+
{
35+
if ((bool)e.NewValue)
36+
{
37+
d.SetCurrentValue(SubscriptionProperty, new SortingSubscription((DataGrid)d));
38+
}
39+
else
40+
{
41+
(d.GetValue(SubscriptionProperty) as IDisposable)?.Dispose();
42+
d.ClearValue(SubscriptionProperty);
43+
}
44+
}
45+
46+
private static void OnDataGridSorting(object sender, DataGridSortingEventArgs e)
47+
{
48+
var dataGrid = (DataGrid)sender;
49+
var sortPropertyName = e.Column.SortMemberPath;
50+
if (!string.IsNullOrEmpty(sortPropertyName))
51+
{
52+
// sorting is cleared when the previous state is Descending
53+
if (e.Column.SortDirection.HasValue && e.Column.SortDirection.Value == ListSortDirection.Descending)
54+
{
55+
e.Column.SetCurrentValue(DataGridColumn.SortDirectionProperty, null);
56+
if ((Keyboard.Modifiers & ModifierKeys.Shift) != ModifierKeys.Shift)
57+
{
58+
var sortDescriptions = dataGrid.Items.SortDescriptions;
59+
for (var i = sortDescriptions.Count - 1; i >= 0; i--)
60+
{
61+
if (sortDescriptions[i].PropertyName == sortPropertyName)
62+
{
63+
sortDescriptions.RemoveAt(i);
64+
}
65+
}
66+
}
67+
else
68+
{
69+
dataGrid.Items.SortDescriptions.Clear();
70+
}
71+
72+
dataGrid.Items.Refresh();
73+
e.Handled = true;
74+
}
75+
}
76+
}
77+
78+
private sealed class SortingSubscription : IDisposable
79+
{
80+
private readonly DataGrid dataGrid;
81+
82+
public SortingSubscription(DataGrid dataGrid)
83+
{
84+
this.dataGrid = dataGrid;
85+
this.dataGrid.Sorting += OnDataGridSorting;
86+
}
87+
88+
public void Dispose()
89+
{
90+
this.dataGrid.Sorting -= OnDataGridSorting;
91+
}
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)