wpf:DataGrid 禁用选定的行样式 - 或行选择

Posted

技术标签:

【中文标题】wpf:DataGrid 禁用选定的行样式 - 或行选择【英文标题】:wpf: DataGrid disable selected row styles - or row selecting 【发布时间】:2011-03-04 02:00:47 【问题描述】:

我看到很多关于如何在 DataGrid 中设置选定行样式的示例,例如:

How can I set the color of a selected row in DataGrid

我可以禁用选定的行样式吗?我不想覆盖所选行更改的每一件事。只是不想要任何可见的变化。必须比创建模板更简单..

或者..

禁用选择行,如果这样更容易的话.. 但是从浏览这个看起来也很hacky的论坛

Disable selecting in WPF DataGrid

【问题讨论】:

【参考方案1】:

想出 XAML 来摆脱选择样式.. 不理想,但足够接近..

<Style x:Key="CellStyle" TargetType="x:Type DataGridCell">
    <Setter Property="Foreground" Value="Black" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="Background" Value="x:Null" />
            <Setter Property="BorderBrush" Value="x:Null" />
        </Trigger>
    </Style.Triggers>
</Style>

【讨论】:

奇怪的是,并没有禁用选定的边框。 这行得通,但我不认为这行:&lt;Setter Property="Foreground" Value="Black" /&gt; 是必要的。 只有在 DataGrid 上的 SelectionUnit 属性设置为“Cell”时才有效 如果我不设置,当你选择一行时,字体颜色为白色(在白色背景上,所以你可以'看不到文字)我把它放在触发器里面,而不是触发器外面。 完美运行。 &lt;Setter Property="Foreground" Value="Black" /&gt; 是必需的。移除后,显示在非焦点单元格中的文本会转动并消失在白色背景中。【参考方案2】:

这对我有用:

<DataGrid>
    <DataGrid.CellStyle>
        <Style TargetType="x:Type DataGridCell">
            <Style.Triggers>
                <Trigger Property="DataGridCell.IsSelected" Value="True">
                    <Setter Property="BorderBrush">
                        <Setter.Value>
                            <SolidColorBrush Color="Transparent"/>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="Foreground"
                            Value="DynamicResource
                                   x:Static SystemColors.ControlTextBrushKey"/>
                    <Setter Property="Background">
                        <Setter.Value>
                            <SolidColorBrush Color="Transparent"/>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGrid.CellStyle>
    <!-- ... -->
</DataGrid>

【讨论】:

这对我也有用。接受的答案无效。【参考方案3】:

我找到了另一种适合我情况的方法。我为所有单元格设置此样式,因为我不希望用户选择任何单元格。

<Style TargetType="x:Type DataGridCell">
    <Setter Property="IsHitTestVisible" Value="False"/>
</Style>

【讨论】:

非常好..我很快就会测试这个 你把它放在 DataGrid XAML 中的什么位置以将它应用到所有单元格? 问题是这对键盘导航没有帮助。 请注意,这也会阻止用户点击单元格中的链接和按钮。 这也会禁用对列的排序【参考方案4】:

我将首先回答第二个问题:要禁用行选择,您可以更改 DataGrid 的 RowStyle。

<DataGrid>
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="IsEnabled" Value="False"/>
        </Style>
    </DataGrid.RowStyle>
    <!--Other DataGrid items-->
</DataGrid>

但是,这会更改文本样式,因为行本身现在已“禁用”。它也不能否定用户仍然可以右键单击该行来选择它的事实。如果您真的想禁用与数据网格行的任何交互,您可以执行以下操作:

<DataGrid>
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="IsHitTestVisible" Value="False"/>
        </Style>
    </DataGrid.RowStyle>
    <!--Other DataGrid items-->
</DataGrid>

由于行仍然启用,文本的样式不会改变。

现在,如果您想更改所选行的样式但不考虑功能,您可以执行以下操作(这与@Dan Stevens 的回答基本相同)。 ControlTextBrushKey 是系统用来为文本项目着色的画笔。请查看this answer 了解 DynamicResource 和 StaticResource 之间的解释。

<DataGrid>
    <DataGrid.CellStyle>
        <Style TargetType="x:Type DataGridCell">
            <Style.Triggers>
                <Trigger Property="DataGridCell.IsSelected" Value="True">
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="Foreground" Value="DynamicResource x:Static SystemColors.ControlTextBrushKey"/>
                    <Setter Property="Background" Value="Transparent"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGrid.CellStyle>
    <!--Other DataGrid items-->
</DataGrid>

需要注意的是,上面的方案在选择行的时候并没有改变DataGridRowHeader的样式,如下图所示(选择了第一行)。

【讨论】:

【参考方案5】:

这个比较简单:

datagrid.SelectionChanged += (obj, e) =>
  Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() =>
    datagrid.UnselectAll()));

这将禁用 DataGrid 上的所有选择。

如果您不想完全禁用选择而只是将其隐藏,则需要修改模板。

【讨论】:

好吧,我试过了,它仍然让我选择。这种覆盖会阻止某些选择,但不是全部。至少在视觉上,我仍然可以看到选中的行。 好的,我也试过了,发现你必须使用 Dispatcher 回调。我的答案中的新代码实际上有效,但现在是三行而不是一行。这对你来说太“hacky”了吗?需要 BeginInvoke 的原因是 MultiSelector 的选择更改处理程序尝试使用自己的 Dispatcher 回调锁定用户的选择更改。 另外,你的代码似乎对我不起作用..(我出于好奇尝试过) hmm.. 如果我错了,请纠正我,但我认为 BeginInvoke 是 Invoke 的异步表亲,因此它肯定在不同的线程上执行。这里没有回调或线程同步,所以我想这不应该导致多线程问题.. 你错了。 Dispatcher 能够在必要时跨线程,但只有在您通过为与您所在的线程不同的线程选择 Dispatcher 来告诉它这样做时才会这样做。当在这样的 UI 对象中使用时,Dispatcher.Invoke 和 Dispatcher.BeginInvoke 只需执行该方法 - 一个同步执行,另一个异步执行。没有其他线程以任何方式、形状或形式参与。很高兴我能为你解决这个问题。我明白您为什么对使用 Dispatcher.BeginInvoke 持怀疑态度,因为您误解了它的作用。【参考方案6】:

对于像我这样有一些不同样式的单元格并且不想覆盖所有样式或为每种样式添加触发器的人来说,这是一个不错的选择:

<DataGrid.Resources>
    <SolidColorBrush 
        x:Key="x:Static SystemColors.HighlightBrushKey" 
        Color="#333333"/>
    <SolidColorBrush 
        x:Key="x:Static SystemColors.HighlightTextBrushKey" 
        Color="Black"/>
    <SolidColorBrush 
        x:Key="x:Static SystemColors.InactiveSelectionHighlightBrushKey" 
        Color="Black"/>
    <SolidColorBrush 
        x:Key="x:Static SystemColors.InactiveSelectionHighlightTextBrushKey" 
        Color="Black"/>
</DataGrid.Resources>

HighlightBrushKey 是带有活动选择的高亮边框,HighlightTextBrushKey 是带有活动选择的文本颜色

就我而言,我希望非活动选择看起来未被选中:

InactiveSelectionHighlightBrushKey 是选择无效时的边框,InactiveSelectionHighlightTextBrushKey 是选择无效时的文本

仅供参考:SystemColors 是一个静态类,是 System.Windows.Media 命名空间的一部分。你可以检查它并无耻地覆盖任何你不喜欢的颜色!

【讨论】:

是否有可以覆盖的 SystemColor 来全局更改禁用单元格的前景色?谢谢。 坦率地说我不知道​​。您可以在 Visual Studio 中键入SystemColors,然后点击alt+f12 以查看其中定义的所有内容,并使用看起来可能是它的颜色进行反复试验,例如其中包含“非活动”的任何内容......跨度> 【参考方案7】:
<Style TargetType="DataGridCell">
    <Style.Triggers>
        <Trigger Property="DataGridCell.IsSelected" Value="True">
            <Setter Property="BorderBrush" Value="Transparent"/> <!--Removes brush color change-->
            <Setter Property="Foreground" Value="Binding RelativeSource=RelativeSource Mode=Self, Path=Foreground"/> <!--Removes foregound change-->
            <Setter Property="Background" Value="Transparent"/>  <!--Removes backgound change-->
        </Trigger>
    </Style.Triggers>
    <Setter Property="FocusVisualStyle" Value="x:Null"/> <!--Removes dotted border when on cell selection change made by keyboard-->
</Style>

我稍微修改了Dan Stevens 和JoshuaTheMiller's 解决方案。在以下情况下使用此解决方案:

您的单元格具有不同的前景色,您应该使用这种方法不要将颜色重置为 SystemColors.ControlTextBrushKey,而是保持其不变 您想禁用鼠标和键盘进行的单元格(和行)选择

【讨论】:

以上是关于wpf:DataGrid 禁用选定的行样式 - 或行选择的主要内容,如果未能解决你的问题,请参考以下文章

WPF Datagrid 样式选定的行

在 DataGrid WPF 中获取选定的行项

如何在 WPF C# 中的 DataGrid 的 TextBoxes 中获取选定的行值

WPF的DataGrid中如何获取当前被选定的行的第一个单元格的值?

怎么改变WPF中DataGrid的行样式

WPF datagrid:禁用某些行中的编辑