2010-12-14 21 views
3

私はMVVMをC#.NETのWPFで使用しています。私は、次の例のモデル持って言う:私の見解ではWPFでオブジェクトのListプロパティをバインドする好ましい方法は何ですか?

public class Dealer 
{ 
    public string Name { get; set; } 
    public List<Car> Cars { get; set; } 
} 

public class Car 
{ 
    public string Make { get; set; } 
    public string Model { get; set; } 
} 

を、私はディーラーのリストを持っている、と私はListViewコントロールでディーラーを選択した場合、私はディーラーの名前を含めて、販売店の詳細を確認すべきであり、車のリスト。

私の質問は、ディーラーオブジェクトのプロパティだから、リストビューにリストをバインドするにはどうすればいいですか?具体的には、ビューモデルにはどのようなものがありますか?コレクションに何かを追加すると更新する車のリストが必要なので、ObservableCollectionが必要な気がします。しかし、これはディーラーごとに2つのコレクション(ListとObservableCollection)を持つことにつながり、このデータの複製はコーディングの視点とパフォーマンスの両方から非効率的に見えます。何か案は?

+0

あなたは絶対に正しいです。私はその質問に答えず、削除された答えを実現しました。 –

答えて

2

私たちが行ってきたことは、ObservableCollection内にModelリストをラップすることでした。このObservableCollectionは通常、ChildオブジェクトのViewModelでもあるため、ビューを制御し、必要に応じてViewModelを別のビューに渡すことができます。 2つのリストがありますが、同じオブジェクト参照が含まれます。それは努力の重複のように見えるかもしれませんが、継承をうまく使用すればDRYのアプローチを維持することができます。 MVVMの考え方は、ビューとモデルの間の抽象化を作成することであることを覚えておいてください.Childオブジェクトをラップしないようにすると、作業を先に保存するように見えるかもしれませんが、これらの子をトランスフォームする必要はほとんどありません後でオブジェクト。

public class DealerViewModel : ViewBase 
{ 
    // This concept can be wrapped in a ListViewBase for a more DRY approach 
    private ObservableCollection<CarViewModel> cars; 
    public ObservableCollection<CarViewModel> Cars 
    { 
     get { return cars; } 
     set { 
      if (cars == value) return; 
      cars = value; 
      RaisePropertyChanged("Cars"); 
     } 
    } 

    // This concept can be wrapped in a ListViewBase for a more DRY approach 
    private CarViewModel selectedCar; 
    public CarViewModel SelectedCar 
    { 
     get { return selectedCar; } 
     set { 
      if (selectedCar== value) return; 
      selectedCar= value; 
      RaisePropertyChanged("SelectedCar"); 
     } 
    } 

    public DealerViewModel(Dealer dealer) 
    { 
     // This concept can be wrapped in a ListViewBase for a more DRY approach 
     Cars = new ObservableCollection(dealer.Cars.Select(c => new CarViewModel(c))); 
    } 
} 

public class CarViewModel 
{ 
} 
2

最初に、リストボックスを使ってリストビューを使用している理由はありますか?使用するかどうかわからない場合は、ListBoxを使用します。あなたのビューモデルに座っているディーラーのリストに1つのListBoxをバインドさせます。ディーラーを追加/削除する場合はObservableCollectionになります。次に、そのListBoxのSelectedValueを、SelectedDealerと呼ばれるビューモデルのDealerプロパティにバインドします。

次に、選択したディーラーの車のリストを表示する2番目のListBoxがあります。 Car ListBoxのDataContextプロパティをSelectedDealerにバインドし、ItemsSourceをCarsにバインドします。その後、あなたの車のリストボックスは、選択されたディーラーに座っている車のコレクションにバインドされます。

車を追加/削除してUIを更新したい場合は、ObservableCollectionを使用します。 ObservableCollectionsを返すビジネスオブジェクトはありませんので、この変換はビューモデルで行う必要があります。おそらく、SelectedCarsというビューモデルにObservableCollectionプロパティを持たせ、あなたのカーリストボックスをこれにバインドすることができます。 SelectedDealer用セッターでは、あなたが何かを行うことができます:あなたがSelectedDealerにあなたの車のリストボックスののDataContextを設定していないでしょう。この場合、

public ObservableCollection<Car> SelectedCars { get; set; } 

private Dealer selectedDealer; 
public Dealer SelectedDealer 
{ 
    get 
    { 
    return this.selectedDealer; 
    } 

    set 
    { 
    if (this.selectedDealer != value) 
    { 
     this.selectedDealer = value; 
     this.SelectedCars = new ObservableCollection(this.SelectedDealer.Cars); 
     OnPropertyChanged(() => this.SelectedDealer); 
    } 
    } 
} 

を、DataContextのは設定されないだろう、とビューモデルを希望暗黙的に使用される。次に、カーリストボックスのItemsSourceをSelectedCarsプロパティにバインドします。

0

personaly私は 'cars'コレクションを 'Stock'オブジェクトをexapleの別のオブジェクトに抽象化します。私はカプセル化を破るので、リストや観測可能なコレクションを公開することはありません。私はStockオブジェクトにaddstockメソッドとremovestockメソッドでienumerableを公開し、関連する動作をカプセル化します。ビューモデルでは、モデル上の対応するメソッドを呼び出し、関連するINotifyPropertyChangedイベントを発生させるという振る舞いがあります。 Stockオブジェクトは独自のビューモデルを持ち、バインディングはviewModelのIEnumerableになります。

関連する問題