2

我很好奇它是如何工作的,因为我有一个MainViewModel,它有一个属性 say SubViewModel,它有一个 ObservableCollection 的属性(我们称之为Property1。)

我已经在所有东西上实现了 INotifyChangedProperty。

我的主窗口

<Window ..
    DataContext="{Binding MainViewModel}" />
...
    <StackPanel DataContext="{Binding SubViewModel}">
        <local:SomeControl DataContext="{Binding}" />
    </StackPanel>
</Window>

还有我的用户控件

<UserControl Name="SomeControl">
    <DataGrid Name="MyDataGrid" ItemSource="{Binding Property1, Mode=TwoWay}" CurrentCellChanged="TestMethod" />
    ...
</UserControl>

在我的测试方法中,为了弄清楚为什么更改没有传播到主视图模型,我做了这样的事情

private void TestMethod()
{
    var vm = this.DataContext as SubViewModel;

    var itemSourceObservableCollection = MyDataGrid.ItemsSource as ObservableCollection<MyType>;

    //I thought vm.Property1 would be equal to itemSourceObservableCollection
    //but they are not, itemSourceObservableCollection shows the changes I've made
    //vm.Property1 has not reflected any changes made, even though I though they were the same item
}

所以我发现 ItemSource 必须创建您绑定到的项目的副本?我被困在这里,如何手动通知 viewModel 该属性已更改并且需要更新?我以为那是 INotifyPropertyChanged 的​​工作?

我认为我的部分问题是我缺乏对这种内部工作方式的理解。如果有人能指出一篇好的博客文章或文档来帮助我理解为什么我的代码没有按我预期的方式工作,那就太好了。

4

2 回答 2

1

1) 没有复制。

2)ObservableCollection将传播对集合所做的更改,而不是集合中的项目。因此,您会看到添加、删除等,但不会看到集合中项目的属性更改。

3) 如果您想查看对 ObservableCollection 中的单个项目所做的更改,您需要INotifyPropertyChanged在这些项目上实现。

于 2013-07-31T11:30:34.513 回答
0

这里实际上有两个不同的问题。当您绑定到集合时,内部会发生什么? 以及为什么用户界面上的更改不会传播回您的视图模型。根据您写的内容,这两个问题没有联系,但让我们一次解决一个问题...

对于第一个问题...当您绑定集合时,WPF 绑定引擎会创建一个“CollectionView”类,该类在您的对象存储和逻辑树之间进行调解。如果需要,您可以使用 CollectionViewSource 上的静态方法获取“CollectionView”的副本...

var cvs = CollectionViewSource.GetDefaultView(MyCollectionOfThings);

结果中有几个有趣的属性,其中一些包含允许您对 CollectionView 进行目录修改的写访问器。

对于第二个问题......您的 SubViewModel 中的业务类需要从 INotifyPropertyChanged 继承,以便通过 WPF 绑定引擎“宣布”更改。您的 VM 应该是发布者,但也可以是订阅者。参与 INotifyPropertyChanged 管道的属性被声明如下......

    private string _name;
    [Description("Name of the driver")]
    public string Name
    {
        [DebuggerStepThrough]
        get { return _name; }
        [DebuggerStepThrough]
        set
        {
            if (value != _name)
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }

此代码发布更改,但也可以通过在 Xaml 中设置适当的属性来订阅在用户界面上所做的更改。

背景阅读: 什么是 CollectionView? 另外,类似的问题

于 2013-07-31T12:45:07.847 回答