Skip to content

Commit 618fb53

Browse files
committed
enhance: select all button.
1 parent faf2ba4 commit 618fb53

File tree

7 files changed

+153
-21
lines changed

7 files changed

+153
-21
lines changed

src/Net_40/HandyControl_Net_40/Themes/Styles/DataGrid.xaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,16 @@
6666
<RowDefinition Height="Auto"/>
6767
<RowDefinition Height="*"/>
6868
</Grid.RowDefinitions>
69-
<Button Command="{x:Static DataGrid.SelectAllCommand}" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType=DataGrid},Converter={StaticResource DoubleMinConverter}}" Style="{StaticResource ButtonIcon}" hc:IconElement.Geometry="{StaticResource AllGeometry}" Foreground="{DynamicResource PrimaryBrush}">
70-
<Button.Visibility>
69+
<hc:SimplePanel Margin="0,0,0,6" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType=DataGrid},Converter={StaticResource DoubleMinConverter}}">
70+
<CheckBox hc:SelectAllButtonAttach.Target="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}}" HorizontalAlignment="Center" />
71+
<hc:SimplePanel.Visibility>
7172
<MultiBinding Converter="{StaticResource DataGridSelectAllButtonVisibilityConverter}">
7273
<Binding Path="HeadersVisibility" RelativeSource="{RelativeSource AncestorType=DataGrid}"/>
7374
<Binding Path="(hc:DataGridAttach.ShowSelectAllButton)" RelativeSource="{RelativeSource AncestorType=DataGrid}"/>
7475
</MultiBinding>
75-
</Button.Visibility>
76-
</Button>
77-
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
76+
</hc:SimplePanel.Visibility>
77+
</hc:SimplePanel>
78+
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Margin="0,0,0,6" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
7879
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
7980
<hc:ToggleBlock VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="1" IsChecked="{Binding HasItems, RelativeSource={RelativeSource AncestorType=DataGrid}, Mode=OneWay}">
8081
<hc:ToggleBlock.UnCheckedContent>

src/Net_40/HandyControl_Net_40/Themes/Theme.xaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12511,15 +12511,16 @@
1251112511
<RowDefinition Height="Auto" />
1251212512
<RowDefinition Height="*" />
1251312513
</Grid.RowDefinitions>
12514-
<Button Command="{x:Static DataGrid.SelectAllCommand}" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType=DataGrid},Converter={StaticResource DoubleMinConverter}}" Style="{StaticResource ButtonIcon}" hc:IconElement.Geometry="{StaticResource AllGeometry}" Foreground="{DynamicResource PrimaryBrush}">
12515-
<Button.Visibility>
12514+
<hc:SimplePanel Margin="0,0,0,6" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType=DataGrid},Converter={StaticResource DoubleMinConverter}}">
12515+
<CheckBox hc:SelectAllButtonAttach.Target="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}}" HorizontalAlignment="Center" />
12516+
<hc:SimplePanel.Visibility>
1251612517
<MultiBinding Converter="{StaticResource DataGridSelectAllButtonVisibilityConverter}">
1251712518
<Binding Path="HeadersVisibility" RelativeSource="{RelativeSource AncestorType=DataGrid}" />
1251812519
<Binding Path="(hc:DataGridAttach.ShowSelectAllButton)" RelativeSource="{RelativeSource AncestorType=DataGrid}" />
1251912520
</MultiBinding>
12520-
</Button.Visibility>
12521-
</Button>
12522-
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
12521+
</hc:SimplePanel.Visibility>
12522+
</hc:SimplePanel>
12523+
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Margin="0,0,0,6" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
1252312524
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
1252412525
<hc:ToggleBlock VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="1" IsChecked="{Binding HasItems, RelativeSource={RelativeSource AncestorType=DataGrid}, Mode=OneWay}">
1252512526
<hc:ToggleBlock.UnCheckedContent>

src/Shared/HandyControlDemo_Shared/UserControl/Styles/DataGridDemo.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<hc:TransitioningContentControl>
1010
<TabControl Style="{StaticResource TabControlInLine}">
1111
<TabItem Header="{ex:Lang Key={x:Static langs:LangKeys.Common}}">
12-
<DataGrid hc:DataGridAttach.CanUnselectAllWithBlankArea="True" HeadersVisibility="All" RowHeaderWidth="60" AutoGenerateColumns="False" ItemsSource="{Binding DataList}">
12+
<DataGrid hc:DataGridAttach.CanUnselectAllWithBlankArea="True" HeadersVisibility="Column" RowHeaderWidth="60" AutoGenerateColumns="False" ItemsSource="{Binding DataList}">
1313
<DataGrid.RowHeaderTemplate>
1414
<DataTemplate>
1515
<CheckBox IsChecked="{Binding IsSelected,RelativeSource={RelativeSource AncestorType=DataGridRow}}"/>
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System.Runtime.CompilerServices;
2+
using System.Windows;
3+
using System.Windows.Controls;
4+
using System.Windows.Controls.Primitives;
5+
6+
namespace HandyControl.Controls;
7+
8+
public class SelectAllButtonAttach
9+
{
10+
private static readonly ConditionalWeakTable<Selector, ToggleButton> SelectorButtonTable = new();
11+
12+
public static readonly DependencyProperty TargetProperty = DependencyProperty.RegisterAttached(
13+
"Target", typeof(Selector), typeof(SelectAllButtonAttach), new PropertyMetadata(null, OnTargetChanged));
14+
15+
public static void SetTarget(DependencyObject element, Selector value)
16+
=> element.SetValue(TargetProperty, value);
17+
18+
public static Selector GetTarget(DependencyObject element)
19+
=> (Selector) element.GetValue(TargetProperty);
20+
21+
private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
22+
{
23+
if (d is not ToggleButton button)
24+
{
25+
return;
26+
}
27+
28+
button.Click -= OnButtonOnClick;
29+
30+
if (e.OldValue is Selector oldSelector)
31+
{
32+
oldSelector.SelectionChanged -= OnSelectorSelectionChanged;
33+
SelectorButtonTable.Remove(oldSelector);
34+
}
35+
36+
if (e.NewValue is not Selector newSelector)
37+
{
38+
return;
39+
}
40+
41+
button.Click += OnButtonOnClick;
42+
newSelector.SelectionChanged += OnSelectorSelectionChanged;
43+
44+
if (!SelectorButtonTable.TryGetValue(newSelector, out _))
45+
{
46+
SelectorButtonTable.Add(newSelector, button);
47+
}
48+
}
49+
50+
private static void OnButtonOnClick(object sender, RoutedEventArgs e)
51+
{
52+
if (sender is not ToggleButton button)
53+
{
54+
return;
55+
}
56+
57+
if (button.IsChecked == true)
58+
{
59+
SelectAll(GetTarget(button));
60+
}
61+
else
62+
{
63+
UnselectAll(GetTarget(button));
64+
}
65+
}
66+
67+
private static void OnSelectorSelectionChanged(object sender, SelectionChangedEventArgs e)
68+
{
69+
if (sender is not Selector selector)
70+
{
71+
return;
72+
}
73+
74+
if (!SelectorButtonTable.TryGetValue(selector, out var button))
75+
{
76+
return;
77+
}
78+
79+
var selectedCount = GetSelectedItemsCount(selector);
80+
var totalCount = selector.Items.Count;
81+
button.IsChecked = selectedCount switch
82+
{
83+
0 => false,
84+
_ when selectedCount == totalCount => true,
85+
_ => null // Indeterminate
86+
};
87+
}
88+
89+
private static void SelectAll(Selector selector)
90+
{
91+
if (selector is MultiSelector multiSelector)
92+
{
93+
multiSelector.SelectAll();
94+
}
95+
else if (selector is ListBox listBox)
96+
{
97+
listBox.SelectAll();
98+
}
99+
}
100+
101+
private static void UnselectAll(Selector selector)
102+
{
103+
if (selector is MultiSelector multiSelector)
104+
{
105+
multiSelector.UnselectAll();
106+
}
107+
else if (selector is ListBox listBox)
108+
{
109+
listBox.UnselectAll();
110+
}
111+
}
112+
113+
private static int GetSelectedItemsCount(Selector selector)
114+
{
115+
if (selector is MultiSelector multiSelector)
116+
{
117+
return multiSelector.SelectedItems.Count;
118+
}
119+
120+
if (selector is ListBox listBox)
121+
{
122+
return listBox.SelectedItems.Count;
123+
}
124+
125+
return 0;
126+
}
127+
}

src/Shared/HandyControl_Shared/HandyControl_Shared.projitems

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<Compile Include="$(MSBuildThisFileDirectory)Controls\Attach\PasswordBoxAttach.cs" />
3131
<Compile Include="$(MSBuildThisFileDirectory)Controls\Attach\RectangleAttach.cs" />
3232
<Compile Include="$(MSBuildThisFileDirectory)Controls\Attach\ScrollViewerAttach.cs" />
33+
<Compile Include="$(MSBuildThisFileDirectory)Controls\Attach\SelectAllButtonAttach.cs" />
3334
<Compile Include="$(MSBuildThisFileDirectory)Controls\Attach\TextBlockAttach.cs" />
3435
<Compile Include="$(MSBuildThisFileDirectory)Controls\Attach\ToggleButtonAttach.cs" />
3536
<Compile Include="$(MSBuildThisFileDirectory)Controls\Base\AdornerElement.cs" />

src/Shared/HandyControl_Shared/Themes/Styles/DataGrid.xaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,16 @@
6666
<RowDefinition Height="Auto"/>
6767
<RowDefinition Height="*"/>
6868
</Grid.RowDefinitions>
69-
<Button Command="{x:Static DataGrid.SelectAllCommand}" MaxHeight="30" Height="auto" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType=DataGrid},Converter={StaticResource DoubleMinConverter}}" Style="{StaticResource ButtonIcon}" hc:IconElement.Geometry="{StaticResource AllGeometry}" Foreground="{DynamicResource PrimaryBrush}">
70-
<Button.Visibility>
69+
<hc:SimplePanel Margin="0,0,0,6" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType=DataGrid},Converter={StaticResource DoubleMinConverter}}">
70+
<CheckBox hc:SelectAllButtonAttach.Target="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}}" HorizontalAlignment="Center" />
71+
<hc:SimplePanel.Visibility>
7172
<MultiBinding Converter="{StaticResource DataGridSelectAllButtonVisibilityConverter}">
7273
<Binding Path="HeadersVisibility" RelativeSource="{RelativeSource AncestorType=DataGrid}"/>
7374
<Binding Path="(hc:DataGridAttach.ShowSelectAllButton)" RelativeSource="{RelativeSource AncestorType=DataGrid}"/>
7475
</MultiBinding>
75-
</Button.Visibility>
76-
</Button>
77-
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
76+
</hc:SimplePanel.Visibility>
77+
</hc:SimplePanel>
78+
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Margin="0,0,0,6" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
7879
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
7980
<hc:ToggleBlock VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="1" IsChecked="{Binding HasItems, RelativeSource={RelativeSource AncestorType=DataGrid}, Mode=OneWay}">
8081
<hc:ToggleBlock.UnCheckedContent>

src/Shared/HandyControl_Shared/Themes/Theme.xaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12647,15 +12647,16 @@
1264712647
<RowDefinition Height="Auto" />
1264812648
<RowDefinition Height="*" />
1264912649
</Grid.RowDefinitions>
12650-
<Button Command="{x:Static DataGrid.SelectAllCommand}" MaxHeight="30" Height="auto" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType=DataGrid},Converter={StaticResource DoubleMinConverter}}" Style="{StaticResource ButtonIcon}" hc:IconElement.Geometry="{StaticResource AllGeometry}" Foreground="{DynamicResource PrimaryBrush}">
12651-
<Button.Visibility>
12650+
<hc:SimplePanel Margin="0,0,0,6" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType=DataGrid},Converter={StaticResource DoubleMinConverter}}">
12651+
<CheckBox hc:SelectAllButtonAttach.Target="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}}" HorizontalAlignment="Center" />
12652+
<hc:SimplePanel.Visibility>
1265212653
<MultiBinding Converter="{StaticResource DataGridSelectAllButtonVisibilityConverter}">
1265312654
<Binding Path="HeadersVisibility" RelativeSource="{RelativeSource AncestorType=DataGrid}" />
1265412655
<Binding Path="(hc:DataGridAttach.ShowSelectAllButton)" RelativeSource="{RelativeSource AncestorType=DataGrid}" />
1265512656
</MultiBinding>
12656-
</Button.Visibility>
12657-
</Button>
12658-
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
12657+
</hc:SimplePanel.Visibility>
12658+
</hc:SimplePanel>
12659+
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Margin="0,0,0,6" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
1265912660
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
1266012661
<hc:ToggleBlock VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="1" IsChecked="{Binding HasItems, RelativeSource={RelativeSource AncestorType=DataGrid}, Mode=OneWay}">
1266112662
<hc:ToggleBlock.UnCheckedContent>

0 commit comments

Comments
 (0)