有条件地将WPF DataGridCell设置为只读

14

我有一个情况,需要根据条件将WPF数据表格单元格设置为只读。在DataGridCell中有IsReadOnly属性,但不幸的是,该属性是只读的!有没有办法实现这个功能?
谢谢。


IsReadOnly 是一个布尔结果,用于检查单元格是否为只读,因此它是一个 readonly 属性 :) - VoodooChild
IsReadOnly属性在DataGrid上是可读/可写的,它是datagrid的根元素。在DataGrid的子元素(如DataGridCell)中,IsReadOnly属性是不可设置的,因为当DataGrid.IsReadyOnly为false时,将DataGridCell.IsReadOnly设置为true是没有意义的。 - VoodooChild
1
@VoodooChild,你不能设置DataGridCell的IsReadOnly属性的主要原因是它们是瞬态的。它们根据需要创建和丢弃,因为DataGrid在任何时候都不会将所有行和单元格保留在内存中。因此,即使它是可写的,你也没有地方可以设置此属性。 - Josh
https://dev59.com/SnI-5IYBdhLWcg3wEEBV - Mohsen
4个回答

11
你应该能够使用DataGrid.BeginningEdit事件有条件地检查单元格是否可编辑,然后在事件参数上设置Cancel属性。

如何防止某些单元格进行编辑的最有效方法是什么?甚至在上一行被编辑后,它也可以防止对单元格的编辑焦点。 - Snail

7
类似于上面的 Goblin 的解决方案,但是这里提供一些代码实例:
思路是动态切换 CellEditingTemplateCellTemplate 两个模板之间,其中一个与 CellTemplate 相同,另一个用于编辑。这使得编辑模式的操作方式与非编辑单元格完全相同。
以下是一些示例代码,需要注意的是此方法需要使用 DataGridTemplateColumn
首先,定义只读和编辑单元格的两个模板:
<DataGrid>
  <DataGrid.Resources>
    <!-- the non-editing cell -->
    <DataTemplate x:Key="ReadonlyCellTemplate">
      <TextBlock Text="{Binding MyCellValue}" />
    </DataTemplate>

    <!-- the editing cell -->
    <DataTemplate x:Key="EditableCellTemplate">
      <TextBox Text="{Binding MyCellValue}" />
    </DataTemplate>
  </DataGrid.Resources>
</DataGrid>

接下来,使用额外的ContentPresenter层定义数据模板,并使用Trigger来切换ContentPresenterContentTemplate,这样上述两个模板就可以通过IsEditable绑定动态切换:

<DataGridTemplateColumn CellTemplate="{StaticResource ReadonlyCellTemplate}">
  <DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
      <!-- the additional layer of content presenter -->
      <ContentPresenter x:Name="Presenter" Content="{Binding}" ContentTemplate="{StaticResource ReadonlyCellTemplate}" />
      <DataTemplate.Triggers>
        <!-- dynamically switch the content template by IsEditable binding -->
        <DataTrigger Binding="{Binding IsEditable}" Value="True">
          <Setter TargetName="Presenter" Property="ContentTemplate" Value="{StaticResource EditableCellTemplate}" />
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

HTH


3
另一个非常简单的解决此问题的方法是使用DataGridCell的样式。
<DataGrid>
    <DataGrid.Resources>
        <Style x:Key="disabledCellStyle" TargetType="DataGridCell">
            <Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
        </Style>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn CellStyle="{StaticResource disabledCellStyle}" />
        <DataGridCheckBoxColumn CellStyle="{StaticResource disabledCellStyle}" />
        <DataGridTextColumn/> /*always enabled*/
    </DataGrid.Columns>
</DataGrid>

这种样式假设ViewModel中有一个IsEnabled属性。

这不会使单元格只读,而是禁用它。虽然几乎是相同的,但它不能被选中。由于此原因,该解决方案可能并不适用于所有情况。


禁用单元格的另一个副作用是,当您按上/下箭头并撞到禁用的单元格时,光标移动会停在那里。如果您有一个应该可以使用键盘遍历的网格,则会产生非常错误的感觉。 - AgostinoX

1
你也可以使用TemplateSelector属性根据你的逻辑设置两个不同的DataTemplates(一个可写,一个只读)。只需创建一个继承自DataTemplateSelector的类,并重写SelectTemplate()方法(在此处可以访问数据上下文)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接