【问题标题】:Disable selecting in WPF DataGrid在 WPF DataGrid 中禁用选择
【发布时间】:2011-01-30 14:35:59
【问题描述】:

如何禁用 WPFTooklit 的 DataGrid 中的选择? 我尝试修改适用于ListView(来自WPF ListView turn off selection)的解决方案,但这不起作用:

<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>

【问题讨论】:

    标签: c# wpf datagrid focus selection


    【解决方案1】:

    这有一个技巧。 您可以处理 DataGrid(比如 dgGrid)的 SelectionChanged 事件并在处理程序中写入:

    dgGrid.UnselectAll();
    

    它将取消选择所有选定的行,结果将是“未选择行”。

    【讨论】:

    • 不工作:这个工作:stackoverflow.com/questions/3046988/…
    • +1 这是一个正确的 :)...无论如何我的在我的情况下工作正常 :)
    • Nikhil 的版本非常适合我。我可以直接在 DataGrid 中编辑单元格,并且整行保持未选中状态。谢谢尼基尔。
    • 你应该避免在/viewmodel后面的代码中与视图逻辑交互
    【解决方案2】:

    正如 Sonic Soul here 所指出的,viky 的解决方案实际上不起作用。

    这是在 DataGrid 中禁用选择的实际工作代码:

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

    【讨论】:

    • 此方法应与将 DataGrid SelectionMode 属性设置为“Single”结合使用...否则您可以在触发事件之前选择多个单元格。
    【解决方案3】:

    另一种简单的方法是使用 IsSelected 触发器将选择样式更改为透明。

    【讨论】:

      【解决方案4】:

      以上所有内容都是易于破解的好主意。但是,他们并没有完全按照要求做。其他答案告诉我们如何取消选择用户选择的内容或隐藏用户选择的内容。

      但是,我理解为什么会给出这些答案。提供真正的解决方案并不容易。

      真正的解决方案是首先防止选择,这并不简单,但只需几个简单的步骤就可以实现。

      回答 1.您必须在Expression Blend中复制样式(或在某处找到样式的副本)。 2. 更改单个 ItemPresenter 设置。我在 ItemPresenter 上设置 IsHitTestVisible="False" 就足够了。

      如果您需要更多详细信息或对此进行深入了解,请参阅我的博文:

      How to disable row selection in a WPF DataGrid?

      【讨论】:

      • 这也不完全正确 - 它会阻止在DataGridCells 上发生点击,这通常是不可取的。
      • 同意。有一天,我将不得不找到一种禁用选择但允许单击的解决方案。
      【解决方案5】:

      干净的方法是,只覆盖行和单元格的样式

      <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>
      

      【讨论】:

      • 这个选项完全被禁用了。我不得不用“透明”替换“{x:Null}”以保持选择工作。这是依偎先生推荐的方式。
      • 仅供参考,不要忘记在触发器中设置&lt;Setter Property="Foreground" Value="Black"/&gt;,否则默认情况下选择的文本将是白色的。
      • @JiBéDoublevé 我只需要这样做,但是我没有使用硬编码值,而是将它放在 DataGridCell 的触发器中:&lt;Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Self}, Path=Foreground}"/&gt;,它将它设置为它已经是什么。奇怪的是,似乎明确地在列定义上设置颜色也会消除颜色变化,而不需要设置器。
      • 如果您想保留默认样式的设置(例如通过 Material Design),那么您可以将其添加到 style 标签:BasedOn="{StaticResource {x:Type DataGridCell}}"BasedOn="{StaticResource {x:Type DataGridRow}}" ... 仅作为结果边框被移除,而不是整个默认样式。
      • 所有控件仍然变蓝怎么办?每个单元格中的TextBlock Backgrounds会变为蓝色,并且在选择行时,我的DatAtmment中的下拉列表和按钮具有蓝色边框。 span>
      【解决方案6】:

      如果您使用替代颜色:

      <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>
      

      【讨论】:

        【解决方案7】:

        只需将IsHitTestVisible="False" 添加到DataGrid 定义。

        【讨论】:

        • 这样可以防止垂直滚动条响应鼠标。
        • 像魅力一样工作...如果您将值绑定到 INPC 属性,那么您可以选择哪些行是可选的 :-)
        • 除了垂直滚动条问题外,这还会禁用鼠标单击子控件。
        【解决方案8】:

        如果其他人面临同样的问题,他们可能会觉得这很有帮助。

        我们需要禁用数据网格上的几行,但同时允许在它们上进行箭头键导航。这就是我们必须切换到“IsHitTestVisible”而不是控制“IsEnabled”属性的原因。所以我们不能采用上述切换到“IsEnable”属性的解决方案。

        这就是我最终解决此问题的方法。我为 DataGridRow 创建了一个新的附加属性 (RowEnable)。此附加属性可以绑定到视图模型属性以控制“虚拟”启用和禁用。我还为 DataGridCell 创建了一个新样式,其中我基于相同的 viewmodel 属性将“IsHitTestVisible”设置为 false。因此,将其视为鼠标/键盘可以看到但看不到其单元格/列的行。这意味着现在我可以根据新的附加属性 (RowEnabled) 设置行的样式,使其看起来被禁用/启用。同时,我可以查看这些几乎被禁用的行的工具提示。

        【讨论】:

          【解决方案9】:

          要完全禁用 DataGrid 中的行选择,您可以执行以下操作:

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

          这可能被认为比设置&lt;Setter Property="IsEnabled" Value="False"/&gt; 更有利,因为执行上述技术会导致行的样式发生变化。它也不会禁用右键单击时出现的上下文菜单。

          最后:请务必注意,将“IsHitTestVisible”设置为“False”会禁用所有与行的交互,包括编辑。

          但是,如果您只想在选中时更改行的样式,请查看答案here

          【讨论】:

          • 这个答案有点救了我的命!
          • 旧答案,但我想对此发表评论。我的解决方案有带有单独 ViewModel 的行。为了完全禁用数据网格,您可以使用 DataGrid.Style 和 TargetType = "DataGrid"。因为我需要控制何时允许选择项目,所以我使用 Value =“{Binding SomeProperty}”,然后该属性必须位于 DataContext 上。如果在使用 RowStyle 设置时属性位于主 DataContext 上,则会出现绑定错误。
          • 这可行,但会阻止点击任何按钮。
          • @Rugbrød:“请务必注意,将“IsHitTestVisible”设置为“False”会禁用与行的所有交互,包括编辑。”这包括点击按钮。
          【解决方案10】:

          我发现这样做的唯一正确方法是禁用 DataGridRowStyle 上的 IsHitTestVisible 属性。

          尽管命名,点击事件仍将注册。确保不要在整个 DataGrid 上更改此属性,除非您还想禁用滚动。

          一种干净的方法是通过静态资源中的新样式(根据需要复制其他设置器)

                  <Style x:Key="DataGridUnselectableRowStyle" TargetType="{x:Type DataGridRow}">
                      <Setter Property="IsHitTestVisible" Value="False"/>
                  </Style>
          

          然后将其绑定到您的 DataGrid 上

                  <DataGrid
                      RowStyle="{StaticResource DataGridUnselectableRowStyle}" >
                      <!-- Contents -->
                  </DataGrid>
          

          【讨论】:

            【解决方案11】:

            我需要一个代码隐藏解决方案。这对我有用:

            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;
            

            【讨论】:

              【解决方案12】:
              <DataGrid isEnabled="False">
              </DataGrid>
              

              这是直接回答您的问题的最简单方法:在 WPF Datagrid 中禁用选择。

              【讨论】:

              • 在 Stack Overflow 上不鼓励仅使用代码的答案,因为它们没有解释它如何解决问题。另外,请编辑您的答案,以解释它是如何工作的,以及它如何改进这个问题已经拥有的许多其他赞成的答案,以便它对其他有类似问题的用户有用。
              • 我认为删除该问题仅有的两个清晰、简洁和正确的答案之一不是一个好主意。你不需要接触代码隐藏,你不需要样式,你不需要提及替代颜色。您所需要的只是一个位置优越的房产。
              • 如果您认为这是一个很好的答案,请将该信息添加到您的答案中!当其他答案更全面时,用户可能不知道这是否适用于这么少的代码,因此您需要告诉他们它是如何工作的以及为什么他们不需要其余的。这就是为什么不鼓励仅使用代码的答案的原因,正如我所解释的那样......如果用户不理解您的答案如何或为什么会起作用(尤其是当有很多其他赞成的答案时),那么这对他们没有太大帮助,或者更糟糕的是——他们甚至可能认为这是错误的。
              • 我很惊讶您对我的答案的高标准,而对读者的期望却如此之低。我认为他们会设法将属性复制并粘贴到他们的数据网格中并查看它是否有效。你想让我夸大答案的一半是题外话:它没有回答问题。
              • 这不是 Stack Overflow 的工作方式。它的目的是充当编程问题的“百科全书”,而这个答案由于缺乏细节而被社区标记为低质量。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-12-12
              • 1970-01-01
              • 2011-06-20
              • 2021-06-23
              相关资源
              最近更新 更多