【发布时间】:2017-11-27 12:11:14
【问题描述】:
我创建了一个 WPF 项目,以明确说明我的项目。
免责声明:我使用 Caliburn.Micro 仅用于使用 PropertyChangedBase 和 BindableCollection。该项目中的其他所有内容都是样板 WPF 内容。
对,所以,我有一个班级DataItem。它只有两个属性:
-
int称为Qty,并且 - 名为
Sum的计算属性,它 是Qty的两倍。
就是这样。为了清楚起见,下面是代码:
public class DataLine : PropertyChangedBase
{
private int qty;
public int Qty
{
get
{
return qty;
}
set
{
if (value == qty)
{
return;
}
qty = value;
NotifyOfPropertyChange();
NotifyOfPropertyChange(() => Sum);
}
}
public int Sum => qty * 2;
public DataLine(int a)
{
Qty = a;
}
}
现在,ViewModel。它有
-
DataLine的BindableCollection(这是 Caliburn 的ObservableCollection风格), - 一个
int,它将把DataLines的所有Sum加起来,并且 - ICommand。
ICommand 只为BindableCollection 和int 触发NotifyPropertyChanged。
代码如下:
class ViewModel: PropertyChangedBase
{
public ViewModel()
{
Data = new BindableCollection<DataLine>
{
new DataLine(1),
new DataLine(2),
new DataLine(4),
new DataLine(6)
};
RefreshCommand = new RefreshCommand(this);
}
private BindableCollection<DataLine> _data;
public BindableCollection<DataLine> Data
{
get
{
return _data;
}
set
{
if (value == _data)
{
return;
}
_data = value;
NotifyOfPropertyChange();
NotifyOfPropertyChange(() => Amount);
}
}
public ICommand RefreshCommand { get; private set; }
public void RefreshAction()
{
NotifyOfPropertyChange(() => Data);
NotifyOfPropertyChange(() => Amount);
}
public int? Amount => Data?.Sum(c => c.Sum);
}
现在,对于View:
很简单。
- 有一个
DataGrid,绑定到BindableCollection。 - 有一个
Button,绑定到ICommand。 - 有一个“TextBox
, bound toAmount”。
这是View 的正文:
<DockPanel>
<TextBox DockPanel.Dock="Bottom" Text="{Binding Amount, TargetNullValue='', Mode=OneWay}"/>
<Button DockPanel.Dock="Bottom" Command="{Binding RefreshCommand}" Content="Refresh"/>
<DataGrid ItemsSource="{Binding Data, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="True"/>
</DockPanel>
当我运行它时,我会得到这样的结果:
现在是棘手的部分 - 让我编辑其中一行。
为了清楚起见,我添加了一个箭头来显示编辑 DataGrid 后光标所在的位置。查看第一行的Sum如何更新,但屏幕底部的Amount保持不变。
现在,当我点击 Refresh 时,会发生这种情况:
Amount 现已正确更新。
所有这些最终让我想到了我的问题:DataGrid 有什么问题?为什么在编辑行时DataGrid 不触发其设置器?以及如何确保它被触发?
【问题讨论】:
-
您是否期望更改 BindableCollection 中对象的属性也会神奇地更改集合属性本身?您的 Data setter 不会因为您编辑集合元素而被调用。那么,“DataGrid 有什么问题”?没什么,只是你的错误期望。
-
当编辑任何子对象时,有没有办法在集合本身上引发
NotifyOfPropertyChange()? -
当然,DataLine 可以通过某种方式访问父视图模型,并调用执行
NotifyOfPropertyChange(() => Amount)的方法 -
但这会将
DataLine与ViewModel紧密结合。是否可以修改 BindableCollection,使其在其任何子项引发PropertyChanged()时引发自己的PropertyChanged()事件? -
我不这么认为。你必须自己做。
标签: c# wpf mvvm datagrid caliburn.micro