2015-12-16 70 views
5

ViewModelをComboBoxにバインドしようとしています。私はこのように定義されたのViewModelクラスを持っている:WPF ComboBoxをViewModelにバインドする

class ViewModel 
{ 
    public ViewModel() 
    { 
     this.Car= "VW"; 
    } 

    public string Car{ get; set; } 
} 

私は同じようWindow_LoadにDataContextのように、このビューモデルを設定します。私のXAMLで次に

private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     this.DataContext = new CarModel(); 
    } 

、私はこれのViewModelに私のコンボボックスをバインドするためにこれを行います。私のコンボボックスでは、デフォルトで選択されたとして、私は「VW」を表示したい:私はデフォルト値コンボボックスに「VW」(一度に選択されたセットにはどうすればよい

  1.  <ComboBox Name="cbCar" SelectedItem="{Binding Car, UpdateSourceTrigger=PropertyChanged}"> 
          <ComboBoxItem Tag="Mazda">Mazda</ComboBoxItem> 
          <ComboBoxItem Tag="VW">VW</ComboBoxItem> 
          <ComboBoxItem Tag="Audi">Audi</ComboBoxItem> 
         </ComboBox> 
    

    私は2つの質問を持っていますフォームの読み込み、コンボボックスに "VW"と表示されます)。

  2. 上記のようなComboBoxItemsをxamlに設定するのではなく、ViewModelで設定してからComboBoxにロードする方法は?

おかげで、

UPDATE: はこれまでのところ、私はこれを実装するために管理が、私はViewModelにはC-TORで以下のようにエラーが出ます:

namespace MyData 
{ 
    class ViewModel 
    { 
     public ViewModel() 
     { 
      this.Make = ""; 
      this.Year = 1; 

      this.DefaultCar = "VW"; //this is where I get error 'No string allowed' 
     } 

     public IEnumerable<Car> Cars 
     { 
      get 
      { 
       var cars = new Car[] { new Car{Model="Mazda"}, new Car{Model="VW"}, new Car{Model="Audi"} }; 
       DefaultCar = cars.FirstOrDefault(car => car.Model == "VW"); 
      } 
     } 

     public string Make { get; set; } 
     public int Year { get; set; } 
     public Car DefaultCar { get; set; } 
    } 

    class Car 
    { 
     public string Model { get; set; } 
    } 
} 
+0

新しい更新、MakeおよびYearプロパティはViewModelではなく、Carクラスに存在する必要があります。 DefaultCarは、文字列ではなくcarのインスタンスに割り当て、ViewModelコンストラクタから削除する必要があります。 –

+0

@ E-Bat ViewModelクラスはIEnumerable の車だけを保持し、それ以外のものはすべてCarクラスに移動する必要がありますか?それともViewModel C-TORから削除するだけですか?この場合、DefaultCarを車のインスタンスに割り当てる方法は?上記の式を使って既に割り当てられていませんか?変更を表示することは可能でしょうか? – pixel

+1

dbnex14この場合、ViewModelにはCarsプロパティとDefaultCarプロパティのみを含める必要があります。 DefaultCarは、データストアからCarsを取​​得した瞬間に割り当てることができます。ビューが読み込まれ、バインディングを解決しようとすると、Carsプロパティがビューから照会されます(ComboBoxのItemsSourceプロパティによってトリガーされます)。次に、リストを返す前にDefaultCarを割り当てることができます。私の答えは以下を参照してください。 –

答えて

7

あなたはMVVMを実装するgointあるとして、あなたはあなたのアプリケーションで車を表現するオブジェクトに考え始めるならば、それはかなり良くなります。

public class ViewModel 
    {  
      public Car SelectedCar{ get; set; } 
      public IEnumerable<Car> Cars{ 
       get { 
        var cars = YOUR_DATA_STORE.Cars.ToList(); 
        SelectedCar = cars.FirstOrDefault(car=>car.Model == "VW"); 
        return cars; 
       } 
      } 
    } 

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

あなたのXAML:

あなたから[OK]を
<ComboBox SelectedItem="{Binding SelectedCar}", ItemsSource="{Binding Cars}" 
     UpdateSourceTrigger=PropertyChanged}"/> 
+0

ありがとうございます。どのようにあなたはこの行を書き換えますか、私は "車"がどこにも定義されていないので、何をしているのかわかりません "SelectedCar = cars.FirstOrDefault(car => car.Model ==" VW ");"? Thansk、 – pixel

+1

@ dbnex14、car変数は、車のコレクション内の各アイテムを表します。前に定義する必要はありません。 syntaxis car =>を見てください。これはラムダ式です。 –

+1

@ dbnex14ラムダ式については、この質問を見てください:http://stackoverflow.com/questions/3970219/c-sharp-lambda –

3
  1. デフォルト値: の場合viewModel.Car = "VW"と設定すると、コンボボックスでその項目が自動的に選択されます。 DataContextを設定する前に、これを実行するには、INotifyPropertyChangedを実装するか、Carに設定する必要があります。

INotifyPropertyChangedの実装が見えるかもしれませんように:

class ViewModel : INotifyPropertyChanged 
{ 
    private string car; 

    public ViewModel() 
    { 
     this.Car = "VW"; 
     this.Cars = new ObservableCollection<string>() { "Mazda", "VW", "Audi" }; 
    } 

    public string Car 
    { 
     get 
     { 
      return this.car; 
     } 
     set 
     { 
      if (this.car != value) 
      { 
       this.car = value; 
       OnPropertyChanged(); 
      } 
     } 
    } 

    public ObservableCollection<string> Cars { get; } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

2. バインドItemsSourceSelectedItem

public ObservableCollection<string> Cars { get; set; } 

:ちょうどリストのプロパティを追加するビューモデルでは

<ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding}" /> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 

<ComboBox ItemsSource="{Binding Cars}" 
      SelectedItem="{Binding Car, Mode=TwoWay}"> 
</ComboBox> 

はまた、あなたのソースまたはビューは単なる文字列を表示するよりも複雑である場合ComboBox.ItemTemplateを設定することができますそれはObservableCollectionである必要はありませんが、そのタイプはコレクションを変更するたびにUIを自動更新します。

+0

どこに車を "マツダ"、 "VW"、 "アウディ"の値に設定しますか?ありがとう – pixel

+1

@ dbnex14車を初期化するための答えを更新 – FUR10N

+0

私は自分のモデルを使用してフォームにいくつかのデフォルト値を設定しています。申し訳ありませんが、私はWPFの新機能ですが、なぜこれが必要なのかを明確にしたいだけです。したがって、フォームが開いているとき、これらの値はデフォルトで私のコントロールに表示されるはずです(この例ではCarコンボボックスですが、他のいくつかのコントロールでアップデートを投稿しました)。 – pixel

関連する問題