2

これがどのように機能するのか興味があります.ObservableCollectionのPropertyを持っているMainViewModelと呼ばれるPropertyを持っているからですSubViewModel(私たちはそれを と呼びます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 の仕事だと思いましたか?

私の問題の一部は、これが内部でどのように機能するかを理解していないことだと思います。私のコードが期待どおりに動作しない理由を理解するのに役立つ良いブログ投稿やドキュメントを誰かが指摘できれば、それは素晴らしいことです。

4

2 に答える 2

1

1) コピーは作成されません。

2)ObservableCollectionコレクション内の項目ではなく、コレクションに加えられた変更を反映します。したがって、追加、削除などは表示されますが、コレクション内のアイテムのプロパティの変更は表示されません。

3) ObservableCollection 内の個々のアイテムに加えられた変更を表示する場合は、それらのアイテムに実装する必要がありINotifyPropertyChangedます。

于 2013-07-31T11:30:34.513 に答える
0

ここには実際には 2 つの異なる問題があります。コレクションにバインドすると、内部で何が起こるでしょうか? そして、ユーザーサーフェスの変更がビュー モデルに反映されない理由。あなたが書いたことに基づいて、2つの問題は関連していませんが、一度に1つずつ見てみましょう...

最初の問題について... コレクションをバインドすると、WPF バインド エンジンは、オブジェクト ストアと論理ツリーの間を仲介する "CollectionView" クラスを作成します。必要に応じて、CollectionViewSource の静的メソッドを使用して「CollectionView」のコピーを取得できます...

var cvs = CollectionViewSource.GetDefaultView(MyCollectionOfThings);

結果にはいくつかの興味深いプロパティがあり、そのうちのいくつかには、CollectionView のディレクトリ変更を可能にする書き込みアクセサーが含まれています。

2番目の問題について... SubViewModelのビジネスクラスは、変更がWPFバインディングエンジンを介して「アナウンス」されるように、INotifyPropertyChangedから継承する必要があります。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 に答える