2015-12-16 11 views
5

Sto provando a collegare il mio ViewModel al mio ComboBox. Ho classe ViewModel definita in questo modo:Collegamento ComboBox WPF al mio ViewModel

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

    public string Car{ get; set; } 
} 

ho impostato questo ViewModel come DataContext in Window_Load come:

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

Poi nel mio XAML, lo faccio per legare il mio ComboBox a questo ViewModel. Voglio mostrare la "VW", come selezionata per impostazione predefinita nella mia casella combinata:

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

Ho 2 domande:

  1. Come faccio a impostare il valore predefinito selezionato in Casella combinata a "VW" (una volta forma carichi, dovrebbe mostrare "VW" nella casella combinata).
  2. Invece di impostare ComboBoxItem come sopra in xaml, come impostarlo nel mio ViewModel e quindi caricarlo in ComboBox?

Grazie,

UPDATE: Finora, riesco a implementare questo, ma ottengo l'errore, come di seguito nel 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 dal le nuove proprietà di aggiornamento, creazione e anno dovrebbero vivere in classe Car, non in ViewModel. DefaultCar dovrebbe essere assegnato a un'istanza di car, non a una stringa, e rimuoverlo dal costruttore ViewModel. –

+0

@ E-Bat Stai dicendo che ViewModel CLASS dovrebbe contenere solo IEnumerable Automobili e tutto il resto dovrebbe essere spostato in Car Class? O dovrei semplicemente rimuoverlo da ViewModel C-TOR? E come assegnare DefaultCar all'istanza di un'auto in questo caso? Non è già assegnato usando l'espressione sopra? Sarebbe possibile mostrare il cambiamento per favore? – pixel

+1

dbnex14, In questo caso ViewModel deve contenere solo le proprietà Cars e DefaultCar. DefaultCar può essere assegnato nel momento stesso in cui ottieni le auto dal tuo archivio dati. Quando la tua vista viene caricata e tenta di risolvere i suoi binding, la proprietà Cars verrà interrogata dalla tua vista (attivata dalla proprietà ItemsSource da ComboBox). Quindi in questo momento puoi assegnare DefaultCar prima di restituire l'elenco. Guarda la mia risposta qui sotto. –

risposta

7

Come siete goint implementare MVVM sarà molto meglio se si inizia a pensare a oggetti per rappresentare Cars nell'applicazione:

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

tuo Xaml:

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

Grazie. come riscriverebbe questa linea, non capisco cosa sta facendo in quanto "auto" non è definita da nessuna parte "SelectedCar = cars.FirstOrDefault (car => car.Model ==" VW ");"? Grazie, – pixel

+1

@ dbnex14, la variabile auto rappresenta ogni elemento della collezione di automobili, non è necessario che sia definito prima. Guarda la sintassi car =>. Questa è un'espressione lambda. –

+1

@ dbnex14 guarda questa domanda per le espressioni lambda: http://stackoverflow.com/questions/3970219/c-sharp-lambda –

3
  1. Valore predefinito: Se hai impostato viewModel.Car = "VW", quindi dovrebbe selezionare automaticamente quell'elemento nella casella combinata. Affinché ciò funzioni, è necessario implementare INotifyPropertyChanged o impostare Car prima di impostare DataContext.

INotifyPropertyChanged implementazione potrebbe essere simile:

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 e SelectedItem.

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

è anche possibile impostare ComboBox.ItemTemplate se la sorgente o vista è più complessa di una semplice visualizzazione di una stringa:

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

Nel modello di visualizzazione è sufficiente aggiungere una proprietà lista:

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

Non deve essere ObservableCollection ma quel tipo aggiornerà automaticamente l'interfaccia utente ogni volta che cambierai la collezione.

+0

Dove mettete Cars ai loro valori "Mazda", "VW", "Audi"? Grazie – pixel

+1

@ dbnex14 ha aggiornato la risposta per inizializzare Cars – FUR10N

+0

Sto utilizzando il mio modello per impostare alcuni valori predefiniti sul modulo. Scusa, sono nuovo di WPF, voglio solo chiarire perché ho bisogno di questo. Quindi, quando i moduli sono aperti, questi valori dovrebbero essere visualizzati di default nei miei controlli (in questo esempio la casella combinata Car, ma ho postato l'aggiornamento con un paio di altri controlli). – pixel