diff --git a/src/Net_40/HandyControl_Net_40/Themes/Styles/DataGrid.xaml b/src/Net_40/HandyControl_Net_40/Themes/Styles/DataGrid.xaml
index 30a41d52..eab03b3f 100644
--- a/src/Net_40/HandyControl_Net_40/Themes/Styles/DataGrid.xaml
+++ b/src/Net_40/HandyControl_Net_40/Themes/Styles/DataGrid.xaml
@@ -66,15 +66,16 @@
-
-
+
+
+
diff --git a/src/Net_40/HandyControl_Net_40/Themes/Theme.xaml b/src/Net_40/HandyControl_Net_40/Themes/Theme.xaml
index 77d33d0c..712a5b22 100644
--- a/src/Net_40/HandyControl_Net_40/Themes/Theme.xaml
+++ b/src/Net_40/HandyControl_Net_40/Themes/Theme.xaml
@@ -12511,15 +12511,16 @@
-
-
+
+
+
diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Styles/DataGridDemo.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Styles/DataGridDemo.xaml
index 435eac69..3bfef1a8 100644
--- a/src/Shared/HandyControlDemo_Shared/UserControl/Styles/DataGridDemo.xaml
+++ b/src/Shared/HandyControlDemo_Shared/UserControl/Styles/DataGridDemo.xaml
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Shared/HandyControl_Shared/Controls/Attach/SelectAllButtonAttach.cs b/src/Shared/HandyControl_Shared/Controls/Attach/SelectAllButtonAttach.cs
new file mode 100644
index 00000000..252c4190
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Controls/Attach/SelectAllButtonAttach.cs
@@ -0,0 +1,127 @@
+using System.Runtime.CompilerServices;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+
+namespace HandyControl.Controls;
+
+public class SelectAllButtonAttach
+{
+ private static readonly ConditionalWeakTable SelectorButtonTable = new();
+
+ public static readonly DependencyProperty TargetProperty = DependencyProperty.RegisterAttached(
+ "Target", typeof(Selector), typeof(SelectAllButtonAttach), new PropertyMetadata(null, OnTargetChanged));
+
+ public static void SetTarget(DependencyObject element, Selector value)
+ => element.SetValue(TargetProperty, value);
+
+ public static Selector GetTarget(DependencyObject element)
+ => (Selector) element.GetValue(TargetProperty);
+
+ private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is not ToggleButton button)
+ {
+ return;
+ }
+
+ button.Click -= OnButtonOnClick;
+
+ if (e.OldValue is Selector oldSelector)
+ {
+ oldSelector.SelectionChanged -= OnSelectorSelectionChanged;
+ SelectorButtonTable.Remove(oldSelector);
+ }
+
+ if (e.NewValue is not Selector newSelector)
+ {
+ return;
+ }
+
+ button.Click += OnButtonOnClick;
+ newSelector.SelectionChanged += OnSelectorSelectionChanged;
+
+ if (!SelectorButtonTable.TryGetValue(newSelector, out _))
+ {
+ SelectorButtonTable.Add(newSelector, button);
+ }
+ }
+
+ private static void OnButtonOnClick(object sender, RoutedEventArgs e)
+ {
+ if (sender is not ToggleButton button)
+ {
+ return;
+ }
+
+ if (button.IsChecked == true)
+ {
+ SelectAll(GetTarget(button));
+ }
+ else
+ {
+ UnselectAll(GetTarget(button));
+ }
+ }
+
+ private static void OnSelectorSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (sender is not Selector selector)
+ {
+ return;
+ }
+
+ if (!SelectorButtonTable.TryGetValue(selector, out var button))
+ {
+ return;
+ }
+
+ var selectedCount = GetSelectedItemsCount(selector);
+ var totalCount = selector.Items.Count;
+ button.IsChecked = selectedCount switch
+ {
+ 0 => false,
+ _ when selectedCount == totalCount => true,
+ _ => null // Indeterminate
+ };
+ }
+
+ private static void SelectAll(Selector selector)
+ {
+ if (selector is MultiSelector multiSelector)
+ {
+ multiSelector.SelectAll();
+ }
+ else if (selector is ListBox listBox)
+ {
+ listBox.SelectAll();
+ }
+ }
+
+ private static void UnselectAll(Selector selector)
+ {
+ if (selector is MultiSelector multiSelector)
+ {
+ multiSelector.UnselectAll();
+ }
+ else if (selector is ListBox listBox)
+ {
+ listBox.UnselectAll();
+ }
+ }
+
+ private static int GetSelectedItemsCount(Selector selector)
+ {
+ if (selector is MultiSelector multiSelector)
+ {
+ return multiSelector.SelectedItems.Count;
+ }
+
+ if (selector is ListBox listBox)
+ {
+ return listBox.SelectedItems.Count;
+ }
+
+ return 0;
+ }
+}
diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
index 0fb7303d..d7aae15d 100644
--- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
+++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
@@ -30,6 +30,7 @@
+
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/DataGrid.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/DataGrid.xaml
index 7fc1fda1..0e7d7d54 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/DataGrid.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/DataGrid.xaml
@@ -66,15 +66,16 @@
-
-
+
+
+
diff --git a/src/Shared/HandyControl_Shared/Themes/Theme.xaml b/src/Shared/HandyControl_Shared/Themes/Theme.xaml
index 31441438..4320f08c 100644
--- a/src/Shared/HandyControl_Shared/Themes/Theme.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Theme.xaml
@@ -12647,15 +12647,16 @@
-
-
+
+
+