我正在使用WPF和.NET 4.0。最近在我的一个程序中,我使用ListView和GridView切换到DataGrid。
我希望能够像在ListView中一样选择并突出显示整行。
在ListView中,当我点击最后一列的空白区域时,我仍然可以选择该行。整行都突出显示,而不仅仅是细胞。
然而,在DataGrid中,在设置SelectionMode =“Single”和SelectionUnit =“FullRow”之后,只有当我点击其中的任何单元格而不是在最后一列的空白区域时,才可以选择该行。
如何在此处使用ListView中的突出显示行为?
答案 0 :(得分:9)
有两种解决方案:
我个人更喜欢第一种解决方案,它比第二种解决方案更干净。
答案 1 :(得分:1)
如果您可以在项目中使用代码,还有一个解决方案。您可以处理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;
}
答案 2 :(得分:1)
根据Aleksey L.先前的评论,以下是带有 FullRowSelect 依赖属性的 DataGridBehavior 类的解决方案。
行为将自动附加MouseDown事件处理程序。 此外,它将设置“ SelectionMode = DataGridSelectionMode.Single ”,以便它可以与 DataContext 和 SelectedItem 绑定一起正常工作。
<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>
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
}
}
答案 3 :(得分:1)
其中一些解决方案在我的情况下不起作用。所以我所做的是将事件重新路由到行的最后一个单元格(最接近点击)。您可以将其添加到行为或代码隐藏中:
_dataGrid.MouseLeftButtonDown += (sender, args) =>
{
//If click was on row border, reroute to latest cell of row
if (!(args.OriginalSource is Border border) || !(border.Child is SelectiveScrollingGrid grid)) return;
var cellsPresenter = grid.Children.OfType<DataGridCellsPresenter>().FirstOrDefault();
if (cellsPresenter == null || cellsPresenter.Items.Count < 1) return;
var lastCell = (DataGridCell)cellsPresenter.ItemContainerGenerator.ContainerFromIndex(cellsPresenter.Items.Count - 1);
lastCell.RaiseEvent(args);
};