C# 在数据网格上编辑单元格后运行方法
我使用WPF和CaliburnMicro绑定数据。我想在每次编辑完单元格后都运行Add()方法,但问题是datagrid的属性没有执行它 这是我的密码:C# 在数据网格上编辑单元格后运行方法,c#,wpf,datagrid,caliburn.micro,C#,Wpf,Datagrid,Caliburn.micro,我使用WPF和CaliburnMicro绑定数据。我想在每次编辑完单元格后都运行Add()方法,但问题是datagrid的属性没有执行它 这是我的密码: <Window x:Class="DataGrid_NotifyOfPropertyChanged.Views.ShellView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x=&
<Window x:Class="DataGrid_NotifyOfPropertyChanged.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataGrid_NotifyOfPropertyChanged.Views"
mc:Ignorable="d"
Title="ShellView" Height="450" Width="800">
<Grid>
<DataGrid x:Name="Numbers" CanUserAddRows="False"/>
</Grid>
ShellViewModel
public class ShellViewModel: Screen
{
public ShellViewModel()
{
Numbers.Add(new NumbersModel { Number = 1 });
Numbers.Add(new NumbersModel { Number = 2 });
}
private BindableCollection<NumbersModel> _numbers = new BindableCollection<NumbersModel>();
public BindableCollection<NumbersModel> Numbers
{
get { return _numbers; }
set {
_numbers = value;
Add();
}
}
public void Add()
{
double result = 0;
foreach(var i in _numbers.ToList())
{
result += i.Number;
}
MessageBox.Show(result.ToString());
}
}
公共类ShellViewModel:屏幕
{
公共ShellViewModel()
{
Add(新的NumbersModel{Number=1});
Add(新的NumbersModel{Number=2});
}
私有BindableCollection_numbers=新的BindableCollection();
公共可绑定集合编号
{
获取{return\u numbers;}
集合{
_数字=数值;
添加();
}
}
公共无效添加()
{
双结果=0;
foreach(变量i在_numbers.ToList()中)
{
结果+=i.编号;
}
Show(result.ToString());
}
}
您必须让NumbersModel
实现INotifyPropertyChanged
接口。这样,您可以在属性发生更改时收到通知。通常,您必须在用作绑定源的每个类上实现此接口。
如果没有这个接口,数据绑定就可以工作,但是性能会急剧下降。对于具有许多绑定的应用程序,这将是一个问题 解决方案是侦听
NumbersModel.Number
的属性更改。因此,我引入了一个专门的事件NumberChanged
事件
NumberChanged
是可选的。您还可以侦听PropertyChanged
,然后使用switch
语句按属性名称筛选所需的属性。我认为一个专门的事件显著地提高了可读性和对上下文的理解,而不是杂乱无章的开关
块
为防止删除项目时内存泄漏,您必须取消订阅您正在收听的NumbersModel
的每个事件。因此,您还需要收听
Numbers
集合的CollectionChanged
事件:
NumbersModel.cs
public class NumbersModel : INotifyPropertyChanged
{
private int number;
public int Number
{
get => this.number;
set
{
if (value == this.number)
{
return;
}
this.number = value;
OnPropertyChanged();
OnNumberChanged();
}
}
public event EventHandler NumberChanged;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnNumberChanged()
{
this.NumberChanged?.Invoke(this, EventArgs.Empty);
}
}
public class ShellViewModel : Screen
{
public ShellViewModel()
{
this.Numbers = new BindableCollection<NumbersModel>();
this.Numbers.Add(new NumbersModel {Number = 1});
this.Numbers.Add(new NumbersModel {Number = 2});
}
public void Add()
{
double result = this._numbers.Sum(numbersModel => numbersModel.Number);
MessageBox.Show(result.ToString());
}
private BindableCollection<NumbersModel> _numbers;
public BindableCollection<NumbersModel> Numbers
{
get => this._numbers;
set
{
// Unsubscribe from old collection
if (this.Numbers != null)
{
this.Numbers.CollectionChanged -= OnCollectionChanged;
}
this._numbers = value;
// Subscribe to new collection
if (this.Numbers != null)
{
this.Numbers.CollectionChanged += OnCollectionChanged;
Add();
}
}
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
{
foreach (NumbersModel newItem in e.NewItems.Cast<NumbersModel>())
{
newItem.NumberChanged += OnNumberChanged;
}
break;
}
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Reset:
{
foreach (NumbersModel newItem in e.OldItems.Cast<NumbersModel>())
{
newItem.NumberChanged -= OnNumberChanged;
}
break;
}
}
}
private void OnNumberChanged(object sender, EventArgs e)
{
Add();
}
}
ShellViewModel.cs
public class NumbersModel : INotifyPropertyChanged
{
private int number;
public int Number
{
get => this.number;
set
{
if (value == this.number)
{
return;
}
this.number = value;
OnPropertyChanged();
OnNumberChanged();
}
}
public event EventHandler NumberChanged;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnNumberChanged()
{
this.NumberChanged?.Invoke(this, EventArgs.Empty);
}
}
public class ShellViewModel : Screen
{
public ShellViewModel()
{
this.Numbers = new BindableCollection<NumbersModel>();
this.Numbers.Add(new NumbersModel {Number = 1});
this.Numbers.Add(new NumbersModel {Number = 2});
}
public void Add()
{
double result = this._numbers.Sum(numbersModel => numbersModel.Number);
MessageBox.Show(result.ToString());
}
private BindableCollection<NumbersModel> _numbers;
public BindableCollection<NumbersModel> Numbers
{
get => this._numbers;
set
{
// Unsubscribe from old collection
if (this.Numbers != null)
{
this.Numbers.CollectionChanged -= OnCollectionChanged;
}
this._numbers = value;
// Subscribe to new collection
if (this.Numbers != null)
{
this.Numbers.CollectionChanged += OnCollectionChanged;
Add();
}
}
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
{
foreach (NumbersModel newItem in e.NewItems.Cast<NumbersModel>())
{
newItem.NumberChanged += OnNumberChanged;
}
break;
}
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Reset:
{
foreach (NumbersModel newItem in e.OldItems.Cast<NumbersModel>())
{
newItem.NumberChanged -= OnNumberChanged;
}
break;
}
}
}
private void OnNumberChanged(object sender, EventArgs e)
{
Add();
}
}
公共类ShellViewModel:屏幕
{
公共ShellViewModel()
{
this.Numbers=new BindableCollection();
this.Numbers.Add(newnumbersmodel{Number=1});
this.Numbers.Add(newnumbersmodel{Number=2});
}
公共无效添加()
{
double result=this.\u numbers.Sum(numbersModel=>numbersModel.Number);
Show(result.ToString());
}
私人BindableCollection\u编号;
公共可绑定集合编号
{
get=>这个;
设置
{
//取消订阅旧收藏
如果(this.Numbers!=null)
{
this.Numbers.CollectionChanged-=OnCollectionChanged;
}
这是一个数值;
//订阅新收藏
如果(this.Numbers!=null)
{
this.Numbers.CollectionChanged+=OnCollectionChanged;
添加();
}
}
}
CollectionChanged的私有void(对象发送方,NotifyCollectionChangedEventArgs e)
{
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
{
foreach(e.NewItems.Cast()中的NumbersModel newItem)
{
newItem.NumberChanged+=OnNumberChanged;
}
打破
}
案例NotifyCollectionChangedAction。删除:
案例通知CollectionChangedAction.Reset:
{
foreach(e.OldItems.Cast()中的NumberModel newItem)
{
newItem.NumberChanged-=OnNumberChanged;
}
打破
}
}
}
私有void OnNumberChanged(对象发送方,事件参数e)
{
添加();
}
}
每次编辑完单元格后,我都要运行Add()
方法
使用Caliburn.Micro执行此操作的方法是使用EventTrigger
和ActionMessage
来处理CellEditEnding
事件:
<DataGrid x:Name="Numbers" CanUserAddRows="False"
cal:Message.Attach="[Event CellEditEnding] = [Action Add()]" />
您可以将逻辑放在数字设置器中。您应该使用更仔细的属性命名。始终在viewmodels上更改jmplement INOTIFYPROPERTY。我已尝试过此操作,但输出不是我所期望的。假设我有两个实例(Number=1和Number=2)。更新datagrid中绑定到Number=1的单元格,并将其替换为2,然后执行Add()方法,结果是3而不是4。我在这里做错了什么吗?如何以及何时更新源属性是另一个主题。如果您有其他问题,请提出新问题。您最初的问题是关于如何“每次编辑完单元格后都运行Add()方法”,是吗?很明显,您不理解“编辑完单元格”。从输出判断,单元格根本没有被编辑。