Выбор полной строки WPF DataGrid
Я использую WPF и .NET 4.0. Недавно в одной из моих программ я переключился с использования ListView с GridView на DataGrid.
Я хочу иметь возможность выбирать и выделять целую строку, как это было в ListView.
В ListView, когда я нажимаю на пустое пространство справа от последнего столбца, я все еще могу выбрать строку. Вся строка подсвечивается не только ячейками.
Однако в DataGrid после установки SelectionMode = "Single" и SelectionUnit = "FullRow" строка выбирается только тогда, когда я нажимаю на любую ячейку в ней, а не в пустое пространство справа до последнего столбца.
Как я могу использовать поведение выделения из ListView здесь?
Ответы
Ответ 1
Существует два решения:
- Установите ширину последнего столбца в DataGrid на Width = "*".
- Второе решение является обходным решением. Добавьте дополнительный пустой столбец после последнего столбца (т.е. Не устанавливая его свойства заголовка или связывания) и установите его ширину в Width = "*"
Я лично предпочитаю первое решение, оно более чистое, чем второе.
Ответ 2
Есть еще одно решение, если вы можете использовать код в своем проекте. Вы можете обрабатывать событие mouse down в datagrid и программно выбирать строку с щелчком:
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;
}
Ответ 3
Основываясь на предыдущем комментарии Алексея Л., вот решение с классом DataGridBehavior с свойством зависимости FullRowSelect.
Поведение автоматически присоединяет обработчик событий MouseDown.
Кроме того, он установит "SelectionMode = DataGridSelectionMode.Single", чтобы он корректно работал с привязкой DataContext и SelectedItem.
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
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
}
}