C# WPF DataGrid:在单元格处于编辑状态时添加行会中断编辑关闭检测
我得到了可以想象得到的最简单的Datagrid,一个按钮绑定到一个命令,该命令向网格所基于的ObservableCollection添加一行。代码非常简单(请参阅下面的MyData类,它只是一堆行) 问题在于:C# WPF DataGrid:在单元格处于编辑状态时添加行会中断编辑关闭检测,c#,wpf,datagrid,C#,Wpf,Datagrid,我得到了可以想象得到的最简单的Datagrid,一个按钮绑定到一个命令,该命令向网格所基于的ObservableCollection添加一行。代码非常简单(请参阅下面的MyData类,它只是一堆行) 问题在于: 添加一行 开始编辑名称单元格 按Add(添加)按钮而不退出编辑单元 现在,对单元格结束编辑的检测已中断。 也就是说,您可以去编辑其他单元格,但不会为它们调用setter。 您可以返回到初始编辑行,按enter键;这样做是因为从现在起编辑开始/结束返回工作正常。 同时,已编辑单元格(但第
您可以返回到初始编辑行,按enter键;这样做是因为从现在起编辑开始/结束返回工作正常。 同时,已编辑单元格(但第一个单元格)的内容将丢失,因为从未调用setter。您所看到的只是图形缓存,所以只需重新排序行并吹!数据不见了 请注意,为了重现该问题,添加按钮必须将Focusable属性设置为false,否则它会工作,因为单击按钮会使Datagrid失去焦点,因此当添加行发生时,单元格不会处于编辑模式。
但不可聚焦是工具栏按钮的典型状态,事实上,我第一次在工具栏上看到这个错误 变通办法 解决方法是将事件关联到代码隐藏中的按钮,以确保datagrid不再处于编辑模式:
private void Button_Click(object sender, RoutedEventArgs e)
{
dg.CommitEdit();
}
但对于所有可能引发行添加的按钮都是必需的。我想要更健壮的东西,并且我想确保以这种方式添加行不会有问题(应该是主流,但我可能会错过同样的东西)
XAML
如果不想尝试解决方法,只需删除Click=“Button\u Click”
<Window x:Class="WpfApp10_DataGridEditingBug.MainWindow"
...
Title="MainWindow" Height="140" Width="280">
<Window.DataContext>
<local:MyData></local:MyData>
</Window.DataContext>
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Command="{Binding AddCommand}" Focusable="False" Click="Button_Click">Add</Button>
</StackPanel>
<DataGrid x:Name="dg" ItemsSource="{Binding People}" CanUserAddRows="False">
</DataGrid>
</DockPanel>
</Window>
为了完整起见,我的smart RelayCommand实现如下:
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public Func<object, bool> CanExecuteFunc;
public Action<object> ExecuteAction;
public bool CanExecute(object parameter) => CanExecuteFunc?.Invoke(parameter) ?? true;
public void Execute(object parameter) => ExecuteAction?.Invoke(parameter);
}
公共类RelayCommand:ICommand
{
公共事件处理程序CanExecuteChanged;
公共职能部门;
公共行动执行;
public bool CanExecute(对象参数)=>CanExecuteFunc?.Invoke(参数)??true;
public void Execute(对象参数)=>ExecuteAction?.Invoke(参数);
}
您可以将绑定的更新资源记录器
设置为属性更改
以立即设置源属性:
private void dg_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.Column is DataGridTextColumn textColumn)
textColumn.Binding = new Binding(e.PropertyName) { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };
}
或者您可以在Person
类中实现。您可能需要添加到Person
。这应该通过ObservableCollection
和Binding
自动发现。可能相关
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public Func<object, bool> CanExecuteFunc;
public Action<object> ExecuteAction;
public bool CanExecute(object parameter) => CanExecuteFunc?.Invoke(parameter) ?? true;
public void Execute(object parameter) => ExecuteAction?.Invoke(parameter);
}
private void dg_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.Column is DataGridTextColumn textColumn)
textColumn.Binding = new Binding(e.PropertyName) { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };
}