Selección de fila completa de WPF DataGrid
listview selection (3)
Estoy usando WPF y .NET 4.0. Recientemente, en uno de mis programas, pasé de usar ListView con GridView a DataGrid.
Quiero poder seleccionar y resaltar toda la fila como pude hacer en ListView.
En ListView, cuando hago clic en el espacio vacío desde la última columna, aún puedo seleccionar la fila. Se resalta toda la fila, no solo las celdas.
Sin embargo, en DataGrid, después de seleccionar SelectionMode = "Single" y SelectionUnit = "FullRow", la fila se puede seleccionar solo cuando hago clic en cualquier celda, no en el espacio vacío que está en la última columna.
¿Cómo puedo usar el comportamiento de resaltado de ListView aquí?
Hay dos soluciones:
- Establezca el ancho de la última columna en el DataGrid en Ancho = "*".
- La segunda solución es una solución. Agregue columna vacía adicional después de la última columna (es decir, no establezca sus propiedades Encabezado ni Enlazar) y configure su ancho en Ancho = "*"
Personalmente prefiero la primera solución, es más limpia que la segunda.
Hay una solución más si puede usar código en su proyecto. Puede manejar el evento de mouse down de la cuadrícula de datos y seleccionar programáticamente la fila cliqueada:
private void SomeGridMouseDown(object sender, MouseButtonEventArgs e)
{
var dependencyObject = (DependencyObject)e.OriginalSource;
//get clicked row from Visual Tree
while ((dependencyObject != null) && !(dependencyObject is DataGridRow))
{
dependencyObject = VisualTreeHelper.GetParent(dependencyObject);
}
var row = dependencyObject as DataGridRow;
if (row == null)
{
return;
}
row.IsSelected = true;
}
Según el comentario anterior de Aleksey L., aquí está la solución con la clase DataGridBehavior con la propiedad de dependencia FullRowSelect .
El comportamiento asociará automáticamente el manejador de eventos MouseDown. Además, establecerá " SelectionMode = DataGridSelectionMode.Single " para que funcione correctamente con DataContext y SelectedItem vinculante.
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>
Clase DataGridBehavior
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
}
}