Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Gu.Wpf.DataGrid2D.Demo/Gu.Wpf.DataGrid2D.Demo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@
<Compile Include="Array2DView.xaml.cs">
<DependentUpon>Array2DView.xaml</DependentUpon>
</Compile>
<Compile Include="ThreeStateSortItem.cs">
<DependentUpon>ThreeStateSortView.xaml</DependentUpon>
</Compile>
<Compile Include="ThreeStateSortView.xaml.cs">
<DependentUpon>ThreeStateSortView.xaml</DependentUpon>
</Compile>
<Compile Include="ThreeStateSortViewModel.cs" />
<Compile Include="TransposedView.xaml.cs">
<DependentUpon>TransposedView.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -166,6 +173,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="ThreeStateSortView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="TransposedView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down
4 changes: 4 additions & 0 deletions Gu.Wpf.DataGrid2D.Demo/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@
<TabItem AutomationProperties.AutomationId="{x:Static demo:AutomationIds.CellTemplateTab}" Header="CellTemplate">
<demo:CellTemplateView />
</TabItem>

<TabItem Header="sort">
<demo:ThreeStateSortView />
</TabItem>
</TabControl>
</Window>
58 changes: 58 additions & 0 deletions Gu.Wpf.DataGrid2D.Demo/ThreeStateSortItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
namespace Gu.Wpf.DataGrid2D.Demo
{
using System.ComponentModel;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;

public class ThreeStateSortItem : INotifyPropertyChanged
{
private string stringValue;
private int intValue;

public event PropertyChangedEventHandler PropertyChanged;

public string StringValue
{
get
{
return this.stringValue;
}

set
{
if (value == this.stringValue)
{
return;
}

this.stringValue = value;
this.OnPropertyChanged();
}
}

public int IntValue
{
get
{
return this.intValue;
}

set
{
if (value == this.intValue)
{
return;
}

this.intValue = value;
this.OnPropertyChanged();
}
}

[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
16 changes: 16 additions & 0 deletions Gu.Wpf.DataGrid2D.Demo/ThreeStateSortView.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<UserControl x:Class="Gu.Wpf.DataGrid2D.Demo.ThreeStateSortView"
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:dataGrid2D="http://gu.se/DataGrid2D"
xmlns:local="clr-namespace:Gu.Wpf.DataGrid2D.Demo"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<UserControl.DataContext>
<local:ThreeStateSortViewModel />
</UserControl.DataContext>

<DataGrid dataGrid2D:Sort.ThreeState="True" ItemsSource="{Binding Items}" />
</UserControl>
15 changes: 15 additions & 0 deletions Gu.Wpf.DataGrid2D.Demo/ThreeStateSortView.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Gu.Wpf.DataGrid2D.Demo
{
using System.Windows.Controls;

/// <summary>
/// Interaction logic for ThreeStateSortView.xaml
/// </summary>
public partial class ThreeStateSortView : UserControl
{
public ThreeStateSortView()
{
this.InitializeComponent();
}
}
}
20 changes: 20 additions & 0 deletions Gu.Wpf.DataGrid2D.Demo/ThreeStateSortViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Gu.Wpf.DataGrid2D.Demo
{
using System.Collections.ObjectModel;

public class ThreeStateSortViewModel
{
public ThreeStateSortViewModel()
{
this.Items = new ObservableCollection<ThreeStateSortItem>
{
new ThreeStateSortItem {StringValue = "a", IntValue = 1},
new ThreeStateSortItem {StringValue = "c", IntValue = 4},
new ThreeStateSortItem {StringValue = "d", IntValue = 2},
new ThreeStateSortItem {StringValue = "b", IntValue = 3},
};
}

public ObservableCollection<ThreeStateSortItem> Items { get; }
}
}
1 change: 1 addition & 0 deletions Gu.Wpf.DataGrid2D/Gu.Wpf.DataGrid2D.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<Compile Include="ItemsSource.Array2D.cs" />
<Compile Include="RowColumnIndex.cs" />
<Compile Include="RowColumnIndexConverter.cs" />
<Compile Include="Sort.cs" />
<Compile Include="Views\Array2DRowView.cs" />
<Compile Include="Views\Array2DView.cs" />
<Compile Include="Views\Array2DIndexPropertyDescriptor.cs" />
Expand Down
94 changes: 94 additions & 0 deletions Gu.Wpf.DataGrid2D/Sort.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
namespace Gu.Wpf.DataGrid2D
{
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

public class Sort
{
public static readonly DependencyProperty ThreeStateProperty = DependencyProperty.RegisterAttached(
"ThreeState",
typeof(bool),
typeof(Sort),
new PropertyMetadata(default(bool), OnThreeStateChanged));

private static readonly DependencyProperty SubscriptionProperty = DependencyProperty.RegisterAttached(
"Subscription",
typeof(SortingSubscription),
typeof(Sort),
new PropertyMetadata(default(SortingSubscription)));

public static void SetThreeState(DependencyObject element, bool value)
{
element.SetValue(ThreeStateProperty, value);
}

public static bool GetThreeState(DependencyObject element)
{
return (bool)element.GetValue(ThreeStateProperty);
}

private static void OnThreeStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
d.SetCurrentValue(SubscriptionProperty, new SortingSubscription((DataGrid)d));
}
else
{
(d.GetValue(SubscriptionProperty) as IDisposable)?.Dispose();
d.ClearValue(SubscriptionProperty);
}
}

private static void OnDataGridSorting(object sender, DataGridSortingEventArgs e)
{
var dataGrid = (DataGrid)sender;
var sortPropertyName = e.Column.SortMemberPath;
if (!string.IsNullOrEmpty(sortPropertyName))
{
// sorting is cleared when the previous state is Descending
if (e.Column.SortDirection.HasValue && e.Column.SortDirection.Value == ListSortDirection.Descending)
{
e.Column.SetCurrentValue(DataGridColumn.SortDirectionProperty, null);
if ((Keyboard.Modifiers & ModifierKeys.Shift) != ModifierKeys.Shift)
{
var sortDescriptions = dataGrid.Items.SortDescriptions;
for (var i = sortDescriptions.Count - 1; i >= 0; i--)
{
if (sortDescriptions[i].PropertyName == sortPropertyName)
{
sortDescriptions.RemoveAt(i);
}
}
}
else
{
dataGrid.Items.SortDescriptions.Clear();
}

dataGrid.Items.Refresh();
e.Handled = true;
}
}
}

private sealed class SortingSubscription : IDisposable
{
private readonly DataGrid dataGrid;

public SortingSubscription(DataGrid dataGrid)
{
this.dataGrid = dataGrid;
this.dataGrid.Sorting += OnDataGridSorting;
}

public void Dispose()
{
this.dataGrid.Sorting -= OnDataGridSorting;
}
}
}
}