0

私は現在、2 つの異なる Entity Framework クラスをラップする ObservableCollections にバインドされた 2 つの同期された ListBoxes で構成される単純なアプリケーションを持っています。

listBox1 の Part 項目が選択されると、SelectedItemのナビゲーション キー情報が listBox2 に渡され、Vendors エンティティのそれぞれのサブセットが表示されます。

現在、私の ViewModel (MainViewModel.cs) は次のようになっています。

public MainViewModel()
{
    _context = new DBEntities();
    _partsCollection = new ObservableCollection<Part>(_context.Parts);
    _vendorsCollection = new ObservableCollection<Vendor>(_context.Vendors);
}

public ObservableCollection<Part> PartsCollection
{
     get { return _partsCollection; }
     set
     {
          OnPropertyChanged("PartsCollection");
          _partsCollection = value;
     }
}


public Observable<Part> SelectedPart
{
     get { return _selectedPart; }
     set
     {
          OnPropertyChanged("SelectedPart");
          _selectedPart = value;
     }
}

public ObservableCollection<Vendor> VendorsCollection
{
     get { return _vendorsCollection; }
     set
     {
          OnPropertyChanged("VendorsCollection");
          _vendorsCollection = value;
     }
}

そして私のビュー(MainView)は次のようになります:

    <UserControl.Resources>
    <local:MainViewModel x:Key="MainViewModelDataSource" />
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource MainViewModelDataSource}}">
           <ListBox ItemsSource="{Binding PartsCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  Margin="43,87,377,57" Name="listBox1"
             SelectedItem="{Binding SelectedPart, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
             IsSynchronizedWithCurrentItem="True" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock FontSize="13" Foreground="Black" Padding="3" Text="{Binding shapeName}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <ListBox IsSynchronizedWithCurrentItem="True" 
             ItemsSource="{Binding ElementName=listbox2,  Path=SelectedItem.Vendors, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Margin="345,87,75,57" 
             >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock FontSize="13" Foreground="Black" Padding="3" Text="{Binding mateStyle}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox> 

これはうまくいきます。ただし、listBox2 をビューモデルのプロパティにバインドして、VendorsCollection. ビューモデルで" " プロパティを使用したいのですがSelectedPart、現在は使用されていません。

EF の全体的なポイントは、変更通知を送信するためだけにビューモデルで追加の ORM を再度構築するのではなく、そのすべての機能を ORM として利用することです。私が見たところ、 のセットアップICollectionViewはかなり回りくどい方法ですが、バインディングを理解することができませんでした。

PropertyChanged通知を発行して Vendors を更新ObservableCollectionし、listBox2 xaml をビューモデルのコレクション プロパティにバインドできるようにするために、次のステップが何であるかはわかりません。

4

2 に答える 2

1

私はMVVMとEntity Frameworkも使用していますが、コードファーストのアプローチを使用しています。ViewModel が変更通知イベントを発生させる必要があるすべての MVVM の「純度」にうんざりしていたので、すべてのモデル クラスに INPC を実装しました。変更を通知するためだけに、ViewModel 内のすべてのモデル プロパティを複製するのはクレイジーです。

DBEntities を使用しているようですが、モデル オブジェクトに変更通知を実装する方法はわかりませんが、実装することを強くお勧めします。私はあなたの人生をずっと楽にします。

ちなみに、次のように、バッキング フィールドを新しい値に設定した後で、必ず OnPropertyChanged イベントを発生させてください。

 set
 {
      _selectedPart = value; //first you change the private backing field
      OnPropertyChanged("SelectedPart"); //then you notify that it has changed, so everything gets the new value
 }

バインディングに関しては、ViewModel の SelectedPart プロパティを使用しています。

SelectedItem="{Binding SelectedPart, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsSynchronizedWithCurrentItem="True"

listbox1 で選択した項目を SelectedPart プロパティにバインドし、IsSynchronizedWithCurrentItem を true に設定することで、UI で何かを選択するたびに ViewModel のプロパティが更新されます (また、SelectedPart をUI が更新を受け取るコード)。

したがって、2 番目のリストボックスで SelectedPart のベンダーにバインドするには、次のようにします。

ItemsSource="{Binding SelectedPart.Vendors, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"

この場合、VendorsCollection を作成する必要はありません。これは、SelectedPart.Vendors を介して同じ要素にアクセスできるためです (または、VendorsCollection を、SelectedPart.Vendor を返す適切な名前のラッパーとして設定することもできます。 null の SelectedPart をチェックします)。

ICollectionView に関しては、Selector から継承する (つまり、SelectedItem プロパティを持っている) FrameworkElements (ListBox など) にバインドするために、ObservableCollection (または類似のもの) の単なるラッパーであることを知っておいてください。

ObservableCollection にバインドすると、WPF はバックグラウンドで ICollectionView を作成するため、SelectedItem を取得します。独自の ICollectionView を作成し、それを ObservableCollection にフィードして、ObservableCollection の場合とまったく同じ方法で XAML の ICollectionView にバインドできます。そうする場合は、ListCollectionView を使用することをお勧めします。これを使用して、グループをフィルター処理および作成できます (ツリービューで使用するため)。

最後に一言: ObservableCollection (およびすべての ICollectionView) は CollectionChanged イベント (つまり、コレクションにアイテムを追加/コレクションからアイテムを削除するとき) のみを発生させることに注意してください。コレクションに属する要素のプロパティを変更しても、それが INotifyPropertyChanged を実装していても、何も発生しません。カスタム コレクションを作成する必要があることを知りたい場合は、ここに (多くの) 例の 1 つを示します。

これがお役に立てば幸いです。

于 2013-01-19T02:27:52.820 に答える
0

すぐに PropertyChanged を取得するには、ObservableCollection を BindingList に渡すだけです。

そのSystem.Data.Entity名前空間のEntityFramework には、そのために役立つToBindingList拡張機能があります。

于 2014-01-17T15:39:23.520 に答える