NotifyOfPropertyChange未在DataGrid

时间:2017-06-23 20:25:56

标签: c# wpf mvvm datagrid caliburn.micro

为了说明我的项目,我创建了一个WPF项目。

免责声明:我仅使用Caliburn.Micro来使用PropertyChangedBaseBindableCollection。此项目中的其他所有内容都是样板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。它已经

  • BindableCollection的{​​{1}}(Caliburn的ObservableCollection风味)DataLine
  • 一个int,它将Sum DataLines的所有NotifyPropertyChanged加起来,
  • ICommand。

ICommand只为BindableCollectionint触发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,绑定到, bound to
  • 有一个&#39; TextBox View Amount`。

这是<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

当我运行它时,我得到这样的东西:

Initial Window

现在是棘手的部分 - 让我只编辑其中一行。

Edited

为了清楚起见,我在编辑Sum后添加了一个箭头来显示光标所在的位置。检查第一行Amount的更新方式,但屏幕底部的Refresh保持不变。

现在,当我点击Amount时,会发生这种情况:

The Updated View

DataGrid现已正确更新。

所有这些最终都让我想到了问题:DataGrid有什么问题?为什么Open()在编辑行时不会触发其setter?我怎样才能确保它被触发?

1 个答案:

答案 0 :(得分:1)

我发现Datagrids并且有时会更新meta / aggregate数据。 目前我同意Clemens的观点,我不确定您是否可以轻松更改BindableCollection以满足您的需求。

但是,在DataLineViewModel之间建立紧密联系的快速解决方案是使用可通过的操作。你总是可以看到一些抽象或泛型。但是我创建了一个简单的代码编辑来显示我的意思。

基本上,您创建了一种机制,使ViewModel可以将Action传递给Object。如果我实现这个,我可能会实现某种形式的Interface或Generic,这使我无法为每个Model添加Action方法。或者至少从具有Notify Action的类继承。为了清晰和易于阅读,生病只需做一个简单的编辑。

在您的DataLine中添加:

//NotifyOfPropertyChange(); //NotifyOfPropertyChange(() => Sum); NotifyFromParent?.Invoke();

到您的Qty制定者,并且:

   public DataLine(int a, System.Action action = null)
   {
     Qty = a;
     NotifyFromParent = action;
   }

   public System.Action NotifyFromParent;

然后在你的ViewModel中你可以去:

Data = new BindableCollection<DataLine>
{
   new DataLine(1, () => RefreshAction()),
   new DataLine(2, () => RefreshAction()),
   new DataLine(4, () => RefreshAction()),
   new DataLine(6, () => RefreshAction())
};

就像我说的那样,你可以让这个更加漂亮。据我所知,您需要创建一种机制来在数据网格中编辑单元格时更新聚合或外部数据,并且您希望更新立即执行所述编辑。