2015-12-16 16 views
5

Próbuję powiązać mój ViewModel z moim ComboBox. Mam klasę ViewModel zdefiniowany następująco:WPF Binding ComboBox do mojego ViewModel

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

    public string Car{ get; set; } 
} 

ustawić ten ViewModel jako DataContext w Window_Load jak:

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

potem w moim XAML, zrobić to wiązać moje ComboBox do tego ViewModel. Chcę pokazać „VW” jako domyślnie zaznaczone w moim ComboBox:

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

mam 2 pytania:

  1. W jaki sposób ustawić wartość domyślną wybrano Combo Box na „VW” (raz formuje obciążenia, powinien pokazywać "VW" w polu kombi).
  2. Zamiast ustawić ComboBoxItems jak wyżej w Xaml, jak ustawić go w moim ViewModel, a następnie załadować je w ComboBox?

Dzięki

UPDATE: Jak dotąd udaje mi się realizować to, ale pojawia się błąd jak poniżej w 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

Ok dostępne na Twoim koncie nowa aktualizacja, marka i rok powinny żyć w klasie samochodów, a nie w ViewModel. Wartość DefaultCar powinna zostać przypisana do instancji samochodu, a nie do napisu i usunąć go z konstruktora ViewModel. –

+0

@ E-Bat Czy mówisz, że ViewModel CLASS powinien zawierać tylko IEnumerable Cars i wszystko inne powinno zostać przeniesione do CLASS CLASS? Czy powinienem po prostu usunąć go z ViewModel C-TOR? I jak przypisać DefaultCar do instancji samochodu w tym przypadku? Czy nie jest już przypisany przy użyciu powyższego wyrażenia? Czy możliwe jest pokazanie zmiany, proszę? – pixel

+1

dbnex14, W tym przypadku ViewModel powinien zawierać tylko właściwości Cars i DefaultCar. DefaultCar można przypisać w momencie, gdy otrzymasz samochody ze swojego magazynu danych. Po załadowaniu widoku i próbie rozwiązania powiązań, ich właściwości Cars będą sprawdzane z poziomu widoku (wywołane przez właściwość ItemsSource z ComboBox). W tym momencie możesz przypisać wartość DefaultCar przed zwróceniem listy. Zobacz moją odpowiedź poniżej. –

Odpowiedz

7

Jak jesteś goint wdrożyć MVVM to będzie dużo lepiej, jeśli zaczniesz myśleć w obiektach do reprezentowania Samochody w aplikacji:

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; } 
    } 

Twój Xaml:

<ComboBox SelectedItem="{Binding SelectedCar}", ItemsSource="{Binding Cars}" 
     UpdateSourceTrigger=PropertyChanged}"/> 
+0

Dzięki. w jaki sposób przepisałbyś tę linię, nie rozumiem, co robi, ponieważ "samochód" nigdzie nie jest zdefiniowany "SelectedCar = cars.FirstOrDefault (car => car.Model ==" VW ");"? Thansk, – pixel

+1

@ dbnex14, zmienna samochodu reprezentuje każdy przedmiot w kolekcji samochodów, nie ma potrzeby definiowania go wcześniej. Spójrz na samochód składniowy =>. To jest wyrażenie lambda. –

+1

@ dbnex14 proszę spojrzeć na to pytanie dla wyrażeń lambda: http://stackoverflow.com/questions/3970219/c-sharp-lambda –

3
  1. Wartość domyślna: If ustawiasz viewModel.Car = "VW", wtedy powinien automatycznie wybrać ten element w polu kombi. Aby to działało, musisz wykonać implementację INotifyPropertyChanged lub ustawić Car przed ustawieniem DataContext.

INotifyPropertyChanged realizacja może wyglądać następująco:

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. Bind ItemsSource i SelectedItem.

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

Można również ustawić ComboBox.ItemTemplate jeśli źródło lub widok jest bardziej skomplikowane niż tylko wyświetlanie znaków:

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

W modelu widoku tylko dodać obiekt listy:

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

Nie musi to być ObservableCollection, ale ten typ automatycznie aktualizuje interfejs użytkownika po każdej zmianie kolekcji.

+0

Gdzie ustawiasz samochody na ich wartości "Mazda", "VW", "Audi"? Dzięki – pixel

+1

@ dbnex14 zaktualizował odpowiedź, aby zainicjować Cars – FUR10N

+0

Używam mojego modelu, aby ustawić niektóre domyślne wartości w formularzu. Przepraszam, jestem nowy w WPF, chcę tylko wyjaśnić, dlaczego tego potrzebuję. Tak więc, gdy formularze są otwarte, wartości te powinny być domyślnie wyświetlane w moich kontrolkach (w tym przykładzie pole kombi samochodu, ale opublikowałem aktualizację z kilkoma innymi kontrolkami). – pixel