Based on previous comment from Aleksey L., here is the solution with DataGridBehavior class with FullRowSelect dependency property.
Behavior will automatically attach MouseDown event handler.
Also, it will set "SelectionMode = DataGridSelectionMode.Single" so it will work properly with DataContext and SelectedItem binding.
XAML
<UserControl x:Class="WpfDemo.Views.Default"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:b="clr-namespace:WpfDemo.Behaviors"
mc:Ignorable="d"
d:DesignHeight="300">
<DataGrid b:DataGridBehavior.FullRowSelect="True">
...
</DataGrid>
DataGridBehavior class
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfDemo.Behaviors
{
/// <summary>
/// Extends <see cref="DataGrid"/> element functionality.
/// </summary>
public static class DataGridBehavior
{
#region - Dependency properties -
/// <summary>
/// Forces row selection on empty cell, full row select.
/// </summary>
public static readonly DependencyProperty FullRowSelectProperty = DependencyProperty.RegisterAttached("FullRowSelect",
typeof(bool),
typeof(DataGridBehavior),
new UIPropertyMetadata(false, OnFullRowSelectChanged));
#endregion
#region - Public methods -
/// <summary>
/// Gets property value.
/// </summary>
/// <param name="grid">Frame.</param>
/// <returns>True if row should be selected when clicked outside of the last cell, otherwise false.</returns>
public static bool GetFullRowSelect(DataGrid grid)
{
return (bool)grid.GetValue(FullRowSelectProperty);
}
/// <summary>
/// Sets property value.
/// </summary>
/// <param name="grid">Frame.</param>
/// <param name="value">Value indicating whether row should be selected when clicked outside of the last cell.</param>
public static void SetFullRowSelect(DataGrid grid, bool value)
{
grid.SetValue(FullRowSelectProperty, value);
}
#endregion
#region - Private methods -
/// <summary>
/// Occurs when FullRowSelectProperty has changed.
/// </summary>
/// <param name="depObj">Dependency object.</param>
/// <param name="e">Event arguments.</param>
private static void OnFullRowSelectChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
DataGrid grid = depObj as DataGrid;
if (grid == null)
return;
if (e.NewValue is bool == false)
{
grid.MouseDown -= OnMouseDown;
return;
}
if ((bool)e.NewValue)
{
grid.SelectionMode = DataGridSelectionMode.Single;
grid.MouseDown += OnMouseDown;
}
}
private static void OnMouseDown(object sender, MouseButtonEventArgs e)
{
var dependencyObject = (DependencyObject)e.OriginalSource;
while ((dependencyObject != null) && !(dependencyObject is DataGridRow))
{
dependencyObject = VisualTreeHelper.GetParent(dependencyObject);
}
var row = dependencyObject as DataGridRow;
if (row == null)
{
return;
}
row.IsSelected = true;
}
#endregion
}
}
Width="*"
: The horizontal scrollbar will no longer be visible if it is needed. – Gardner