You have two choices:
You disable selection in style (in this case you turn off only color in style, but physically SelectedItem or SelectedItems will change). You can easily find out how you can turn off selection style.
You can disable changing selection without changing SelectedItem or SelectedItems (in this case your selection style will not change too).
In WPF i don't like to override standard controls. So, we need a Behavior
:
public class DisableSelectionDataGridBehavior : Behavior<DataGrid>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObjectOnPreviewMouseLeftButtonDown;
}
private void AssociatedObjectOnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var dependencyObject = AssociatedObject.InputHitTest(e.GetPosition(AssociatedObject)) as DependencyObject;
if (dependencyObject == null) return;
var elements = dependencyObject.GetParents().OfType<FrameworkElement>().Where(DataGridCellExtended.GetIsDisableSelection).ToList();
if (!elements.Any()) return;
e.Handled = true;
var args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton, e.StylusDevice);
args.RoutedEvent = UIElement.MouseLeftButtonDownEvent;
args.Source = e.Source;
elements.ForEach(item =>
{
item.RaiseEvent(args);
var children = item.GetChildren<FrameworkElement>();
children.ForEach(child => child.RaiseEvent(args));
});
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObjectOnPreviewMouseLeftButtonDown;
}
}
Second, you need an Extended
class:
public class DataGridCellExtended
{
public static readonly DependencyProperty IsDisableSelectionProperty = DependencyProperty.RegisterAttached("IsDisableSelection", typeof(Boolean), typeof(DataGridCellExtended));
public static Boolean GetIsDisableSelection(DependencyObject o)
{
return (Boolean)o.GetValue(IsDisableSelectionProperty);
}
public static void SetIsDisableSelection(DependencyObject o, Boolean value)
{
o.SetValue(IsDisableSelectionProperty, value);
}
}
And finally in XAML you need something like this:
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type items:YourViewModel}">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Button Margin="0"
extends:DataGridCellExtended.IsDisableSelection="True">
<Path Data="M5,0L3,2 1,0 0,1 2,3 0,5 1,6 3,4 5,6 6,5 4,3 6,1z"
Fill="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridCell}}"
Width="12"
Height="12"
Stretch="Uniform"/>
</Button>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
You can write your logic for extended class.
public static IEnumerable<DependencyObject> GetParents(this DependencyObject element)
{
if (element != null)
{
while (true)
{
var parent = element.GetParent();
var dependencyObject = parent;
element = parent;
if (dependencyObject == null)
{
break;
}
yield return element;
}
yield break;
}
else
{
throw new ArgumentNullException("element");
}
}
private static IEnumerable<DependencyObject> GetChildrenRecursive(this DependencyObject element)
{
if (element != null)
{
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var dependencyObject = VisualTreeHelper.GetChild(element, i);
yield return dependencyObject;
foreach (var childrenRecursive in dependencyObject.GetChildrenRecursive())
{
yield return childrenRecursive;
}
}
}
else
{
throw new ArgumentNullException("element");
}
}