修改CellEditEnding事件的DataGrid单元格值
本文关键字:单元格 DataGrid CellEditEnding 事件 修改 | 更新日期: 2023-09-27 18:26:39
我一直试图在WPF DataGrid控件的CellEditEnding事件处理程序中更改同一行中的不同单元格值。
如果编辑现有行中的单元格值,它将按预期工作。但是,添加新行时,如果鼠标单击另一个单元格值而不进入编辑模式,则更改不会反映到UI中。
按tab键将焦点移动到下一个单元格也可以正常工作,但它不应该也适用于单击吗?
public MainWindow()
{
InitializeComponent();
DataTable dataTable = new DataTable();
dataTable.Columns.Add(new DataColumn());
dataTable.Columns.Add(new DataColumn());
DataRow existingRow = dataTable.NewRow();
dataTable.Rows.Add(existingRow);
this.MyDataGrid.ItemsSource = dataTable.DefaultView;
this.MyDataGrid.CellEditEnding += MyDataGrid_CellEditEnding;
}
void MyDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
(e.Row.Item as DataRowView).Row[1] = "a string that should be displayed immediatly";
}
到目前为止,我已经尝试更改绑定UpdateSourceTrigger、NotifyOnSourceUpdated和NotifyOnTargetUpdated,但似乎什么都不起作用。我还试着通过阅读相关主题来进行相应的修复:http://codefluff.blogspot.fi/2010/05/commiting-bound-cell-changes.html
但这些似乎也无济于事。。
我发现的一种工作方式是以下片段:
var frameworkElement = this.MyDataGrid.Columns[1].GetCellContent(e.Row);
frameworkElement.SetValue(TextBlock.TextProperty, "a string that should be displayed immediatly");
但我不想依赖dependencyproperties,因为我可能不知道底层的显示类型。
因此,问题是,在不使用提供的第二个代码片段的情况下,如何在新行中实现UI更新?我觉得我错过了什么。。
编辑:使用剪贴板粘贴也可以设置新值,但由于某些原因,原始编辑值将丢失。
第2版:xaml目前是纯DataGrid,我曾尝试手动完成列及其绑定,但由于我没有让它们工作,我已经删除了它们,以保持示例代码的简单
<DataGrid x:Name="MyDataGrid" />
第3版:添加此图片以更好地描述问题。因此,在单击下一个单元格后,我希望显示文本问题的示例图像
Edit4:使用snoop查看单元格似乎将元素设置为可见,同时调用.UpdateTarget();因为绑定似乎有帮助,但它不是自动工作的。还在想是什么原因。。
第5版:我希望这能与DataTable一起使用,因为我需要它的其他功能
在测试了大量不同类型的解决方案后,我在开始编辑单元格时添加了行。由于我所寻求的功能是在现有行中工作,所以它确实解决了问题。
public class MyDataGrid : DataGrid
{
protected override void OnBeginningEdit(DataGridBeginningEditEventArgs e)
{
base.OnBeginningEdit(e);
this.CommitEdit();
}
protected override void OnCellEditEnding(DataGridCellEditEndingEventArgs e)
{
base.OnCellEditEnding(e);
(e.Row.Item as DataRowView).Row[1] = "a string that should be displayed immediatly";
}
}
我建议您使用MVVM的方式,然后您将通过WPF本身的内置通知机制来满足您的要求,在数据上下文中某个属性的upfdate上,您可以触发另一个属性的更新。示例:1.Xaml编码:
<Window x:Class="DataGridSoHelpAttempt.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dataGridSoHelpAttempt="clr-namespace:DataGridSoHelpAttempt"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<dataGridSoHelpAttempt:MainViewModel/>
</Window.DataContext>
<Grid>
<DataGrid x:Name="MyDataGrid" ItemsSource="{Binding DataSource}"/>
</Grid></Window>
2.查看型号代码:
public class MainViewModel:BaseObservableObject
{
public MainViewModel()
{
DataSource = new ObservableCollection<BaseData>(new List<BaseData>
{
new BaseData {Name = "John"},
new BaseData {Name = "Ron"},
new BaseData {Name = "Bob"},
});
}
public ObservableCollection<BaseData> DataSource { get; set; }
}
3.型号代码:
public class BaseData:BaseObservableObject
{
private string _name;
private string _description;
public virtual string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
Description = "a string that should be displayed immediatly";
}
}
public virtual object Description
{
get { return _description; }
set
{
_description = (string) value;
OnPropertyChanged();
}
}
}
4.BaseObservableObject一个基本的INotifyPropertyChanged实现:
public class BaseObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> raiser)
{
var propName = ((MemberExpression)raiser.Body).Member.Name;
OnPropertyChanged(propName);
}
protected bool Set<T>(ref T field, T value, [CallerMemberName] string name = null)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
OnPropertyChanged(name);
return true;
}
return false;
}
}
5.请记住,您的模型的属性对象可能很复杂(如描述另一个视图模型的图像或类),但在这种情况下,您必须对数据网格列或/和单元格进行模板化(示例链接:WPF DataGrid控件)。
如果您在代码方面遇到问题,我将非常乐意为您提供帮助。问候
更新1.代码隐藏-您应该更新DataTable,但请考虑到必须对表中已经存在的行执行更新:
public partial class MainWindow : Window
{
private readonly DataTable _dataTable;
public MainWindow()
{
InitializeComponent();
this.MyDataGrid.CellEditEnding += MyDataGrid_CellEditEnding;
_dataTable = new DataTable();
_dataTable.Columns.Add(new DataColumn());
_dataTable.Columns.Add(new DataColumn());
DataRow existingRow = _dataTable.NewRow();
_dataTable.Rows.Add(existingRow);
this.MyDataGrid.ItemsSource = _dataTable.DefaultView;
}
void MyDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
var dataRowView = (e.Row.Item as DataRowView);
var columnIndex = e.Column.DisplayIndex;
var rowIndex = e.Row.GetIndex();
var dv = _dataTable.DefaultView;
var nextColumnIndex = columnIndex + 1;
if (dv.Table.Columns.Count <= nextColumnIndex || dv.Table.Rows.Count <= rowIndex) return;
dv.Table.Rows[rowIndex][nextColumnIndex] = "a string that should be displayed immediatly";
}
}
2.Xaml:
<Window x:Class="GridViewWitaFDataTableSoHelpAttempt.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="MyDataGrid" />
</Grid></Window>