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

C# 当您绑定到ItemSource时,内部会发生什么?,c#,wpf,data-binding,mvvm,itemssource,C#,Wpf,Data Binding,Mvvm,Itemssource,我很好奇它是如何工作的,因为我有一个MainViewModel,它的属性称为SubViewModel,它的属性为observeCollection(我们称之为Property1) 我已经在所有东西上实现了INotifyChangedProperty 我的主窗口 <Window .. DataContext="{Binding MainViewModel}" /> ... <StackPanel DataContext="{Binding SubViewModel

我很好奇它是如何工作的,因为我有一个
MainViewModel
,它的属性称为
SubViewModel
,它的属性为observeCollection(我们称之为
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
}
private void TestMethod()
{
var vm=this.DataContext作为子视图模型;
var itemSourceObservableCollection=MyDataGrid.ItemsSource作为ObservableCollection;
//我认为vm.Property1将等于itemSourceObservableCollection
//但事实并非如此,itemSourceObservableCollection显示了我所做的更改
//vm.Property1未反映所做的任何更改,即使我认为它们是同一项
}
所以我发现ItemSource必须创建绑定到的项的副本?我被困在这里,如何手动通知viewModel此属性已更改,需要更新?我以为那是InotifyProperty改变了他的工作

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

1)没有复制

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


3) 如果要查看对ObservableCollection中单个项所做的更改,则需要对这些项实施
INotifyPropertyChanged

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

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

var cvs = CollectionViewSource.GetDefaultView(MyCollectionOfThings);
结果中有几个有趣的属性,其中一些包含写访问器,允许您对CollectionView进行目录修改

关于第二个问题。。。子视图模型中的业务类需要从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中设置适当的属性来订阅在用户界面上所做的更改

背景资料:
另外,

更改不符合主视图模型-什么样的更改?Afaik
Mode=TwoWay
不支持
ItemsSource
。我以为这是INotifyPropertyChanged的工作?不,这只适用于其他方向(ViewModel->View)。@HenkHolterman,wadr,它在模板上受支持items@GarryVass-TwoWay适用于单个项目,但您不能通过ItemsSource插入/删除。@HenkHolterman,当此属性设置为true时,数据网格底部将显示一个空行。用户可以在空白行中输入新项。添加新行会将项目添加到ItemsSource。通过处理InitializingNewItem事件并以编程方式设置值,可以为新项设置默认值。