繁体   English   中英

当您绑定到ItemSource时,内部会发生什么?

[英]What happens internally when you bind to ItemSource?

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

我已经在所有内容上实现了INotifyChangedProperty。

我的主视窗

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

还有我的UserControl

<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的工作?

我认为部分问题是我对这种内部运作方式缺乏了解。 如果任何人都可以指向一个好的博客文章或文档来帮助我理解为什么我的代码无法按我预期的方式工作,那将很棒。

1)没有复印。

2) ObservableCollection将提议对集合所做的更改,而不是对集合中的项目的更改。 因此,您将看到添加,删除等信息,但是集合中项目的属性未更改。

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

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

对于第一个问题...绑定集合时,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? 另外, 类似的问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM