如何禁用 WPFTooklit 的
DataGrid
中的选择?
我尝试修改适用于 ListView
的解决方案(来自 WPF ListView 关闭选择),但这不起作用:
<tk:DataGrid>
<tk:DataGrid.ItemContainerStyle>
<Style TargetType="{x:Type tk:DataGridRow}">
<Setter Property="Focusable" Value="false"/>
</Style>
</tk:DataGrid.ItemContainerStyle>
<tk:DataGrid.CellStyle>
<Style TargetType="{x:Type tk:DataGridCell}">
<Setter Property="Focusable" Value="false"/>
</Style>
</tk:DataGrid.CellStyle>
</tk:DataGrid>
干净的方法是,只覆盖行和单元格的样式
<DataGrid.Resources>
<ResourceDictionary>
<Style x:Key="{x:Type DataGridCell}" TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</DataGrid.Resources>
要完全禁用 DataGrid 中的行选择,您可以执行以下操作:
<DataGrid>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
</DataGrid.RowStyle>
<!--Other DataGrid items-->
</DataGrid>
这可能被认为比设置
<Setter Property="IsEnabled" Value="False"/>
更有利,因为执行上述技术会导致行的样式发生变化。它也不会禁止右键单击时显示上下文菜单。
最后:请务必注意,将“IsHitTestVisible”设置为“False”会禁用所有与行的交互,包括编辑。
但是,如果您只想在选择时更改行的样式,请在此处查看答案。
只需将
IsHitTestVisible="False"
添加到 DataGrid
定义即可。
以上所有都是轻松破解的好主意。然而,他们并没有完全按照要求去做。其他答案告诉我们如何取消选择用户选择的某些内容或隐藏用户选择某些内容的事实。
不过,我明白为什么会给出这些答案。提供真正的解决方案并不容易。
真正的解决方案是首先阻止选择,这并不简单,但可以通过几个简单的步骤来实现。
回答 1. 您必须在 Expression Blend 中复制样式(或在某处找到样式的副本)。 2. 更改单个 ItemPresenter 设置。 对我来说,在 ItemPresenter 上设置 IsHitTestVisible="False" 就足够了。
如果您需要更多详细信息或深入的操作步骤,请参阅我的博客文章:
正如 Sonic Soul here 所指出的,viky 的解决方案实际上不起作用。
这是在 DataGrid 中禁用选择的实际工作代码:
grid.SelectionChanged += (obj, e) =>
Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() =>
grid.UnselectAll()));
我发现执行此操作的唯一正确方法是禁用 DataGridRowStyle 上的 IsHitTestVisible 属性。
尽管命名,点击事件仍然会注册。确保不要在整个 DataGrid 上更改此属性,除非您还想禁用滚动。
执行此操作的一种简洁方法是通过静态资源中的新样式(根据需要复制其他设置器)
<Style x:Key="DataGridUnselectableRowStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
然后将其绑定到您的 DataGrid 上
<DataGrid
RowStyle="{StaticResource DataGridUnselectableRowStyle}" >
<!-- Contents -->
</DataGrid>
另一种简单的方法是使用 IsSelected 触发器将选择样式更改为透明。
如果您使用替代颜色:
<Style TargetType="{x:Type DataGrid}">
<Setter Property="RowBackground" Value="#badeee"/>
<Setter Property="AlternationCount" Value="2" />
<Setter Property="AlternatingRowBackground" Value="#92cce5"/>
</Style>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#badeee"></Setter>
<Setter Property="BorderBrush" Value="#badeee"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#92cce5"></Setter>
<Setter Property="BorderBrush" Value="#92cce5"></Setter>
</Trigger>
</Style.Triggers>
</Style>
根据此线程的一些答案,我想出了解决方案。
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
</DataGrid.RowStyle>
此选项不会使数据网格、行、单元格或标题变灰。它允许滚动并且不需要后面的代码。
如果其他人也面临同样的问题,他们可能会发现它很有帮助。
我们需要禁用数据网格上的几行,但同时允许在它们上使用箭头键导航。这就是为什么我们必须切换到“IsHitTestVisible”而不是控制“IsEnabled”属性。所以我们不能采用上述切换到“IsEnable”属性的解决方案。
这就是我最终解决这个问题的方法。我为 DataGridRow 创建了一个新的附加属性 (RowEnable)。此附加属性可以绑定到视图模型属性以控制“虚拟”启用和禁用。我还为 DataGridCell 创建了一个新样式,根据相同的 viewmodel 属性将“IsHitTestVisible”设置为 false。因此,将其视为鼠标/键盘可以看到的行,但看不到其单元格/列。这意味着现在我可以根据新的附加属性 (RowEnabled) 设置行的样式,以使其看起来已禁用/已启用。同时,我可以查看这些实际上已禁用的行的工具提示。
我需要一个代码隐藏解决方案。这对我有用:
controlGrid.SelectedCellsChanged += (sender, e) =>
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Render, new Action(() =>
controlGrid.UnselectAll()));
controlGrid.Columns.Clear();
因为有时会闪烁,所以BackgroundProperty也要设置为透明。
Style dataGridCellStyle = new Style(typeof(DataGridCell));
Setter newSetterCell = new Setter(DataGridCell.BackgroundProperty, Brushes.Transparent);
dataGridCellStyle.Setters.Add(newSetterCell);
controlGrid.CellStyle = dataGridCellStyle;
<DataGrid isEnabled="False">
</DataGrid>
这是直接回答您的问题的最简单方法:在 WPF Datagrid 中禁用选择。
要禁用 DataGrid 中单元格和列的选择,并且不限制单元格中控件的交互性,我使用以下解决方案:
将 PreviewMouseDown 添加到 XAML 中的 DataGrid:
<DataGrid PreviewMouseDown="DataGrid_DisableSelection">
并在cs中定义DataGrid_DisableSelection:
private void DataGrid_DisableSelection(object sender, MouseButtonEventArgs e)
{
e.Handled = true; // Selektion verhindern
}
有一个技巧可以做到这一点。 您可以处理 DataGrid(例如 dgGrid)的 SelectionChanged 事件并在处理程序中写入:
dgGrid.UnselectAll();
它将取消选择所有选定的行,结果将是“未选择行”。