解决此问题的一种方法是基于此答案中的代码:
How to make WPF DataGridCell ReadOnly?
使用数据触发器切换单元格的模板。
万一以某种方式被孤立,来自那里的标记是:
<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>
和
<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>
您需要一个属性来驱动该 Datatrigger。
定义一个代表每一行的视图模型(rowViewModel)。
每列都需要一个公共属性。
然后,您需要该数据触发器的新属性,该属性将显示它是否为新行。称之为 IsNew (或任何你喜欢的)。将 Itemssource 绑定到 RowViewModel 的可观察集合。 IsNew 的默认值应为 true。当您从数据库中读取旧数据时,将 IsNew 设置为 false。
然后,您需要将该方法应用于除最后一列之外的所有列。
这会很笨重,但您总共只有 4 列。粘贴非常相似的标记 3 次是不优雅的,但并非如此。一旦你让它以这种方式工作,你就可以考虑是否要重构和整理它。
另一种选择是使用两个数据网格。
在堆栈面板中将一个放在另一个下方。
隐藏第二个标题。
仅用于插入。
然后,您不会在同一个数据网格中编辑新行,因此它的所有列都可以是常规列。
顶部有只读列。
如果用户可以使用顶部数据网格上的标题来调整列宽,您需要绑定列宽,这样它们就不会失步。
第三个选项。
使用完全独立的面板而不是数据网格插入。
我通常根本不允许用户在数据网格中进行编辑,因为这样更难验证,而且用户可能倾向于认为这只是一种 excel 体验,而不是严肃的业务数据。
我使用了一个覆盖面板。
https://social.technet.microsoft.com/wiki/contents/articles/29777.wpf-property-list-editing.aspx
用户要么单击插入按钮,要么在数据网格中选择一行并单击编辑按钮。