2015-06-06 53 views
1

我有一個ViewModel,它有一個集合和一個屬性,表示集合中的選定值。在我看來,這是顯示在一個組合框。當「填充」我的ViewModel時,選定的項目不會顯示在我的視圖中。ComboBox中所選屬性未顯示

我的視圖模型

public class DriverViewModel : MasterDataWithAddressViewModel<Driver> 
{ 
    public ObservableCollection<Vehicle> Vehicles 
    { 
     get { return _vehicles; } 
     set 
     { 
      if (_vehicles != value) 
      { 
       _vehicles = value; 
       RaisePropertyChanged("Vehicles"); 
      } 
     } 
    } 
    public Vehicle SelectedVehicle 
    { 
     get { return PrimaryModel.Vehicle; } 
     set 
     { 
      if (PrimaryModel.Vehicle != value) 
      { 
       PrimaryModel.Vehicle = value; 
       RaisePropertyChanged("SelectedVehicle"); 
      } 
     } 
    } 
} 

SelectedVehicle設置器正確調用,所以是RaisePropertyChanged("SelectedVehicle"); ...

我的ComboBox

<ComboBox DisplayMemberPath="Number" 
      ItemsSource="{Binding Vehicles, UpdateSourceTrigger=PropertyChanged}" 
      SelectedValue="{Binding SelectedVehicle, UpdateSourceTrigger=PropertyChanged}" /> 

我也嘗試過那樣:

<ComboBox DisplayMemberPath="Number" 
      ItemsSource="{Binding Vehicles, UpdateSourceTrigger=PropertyChanged}" 
      SelectedItem="{Binding SelectedVehicle, UpdateSourceTrigger=PropertyChanged}" 
      IsSynchronizedWithCurrentItem="True" /> 

通過「手動」(通過視圖)在ComboBox中選擇一個值沒有問題。通過在代碼中「填充」ViewModel來做到這一點是行不通的。

任何人都可以幫忙嗎?

+0

如果Set被調用,Get不是,那麼你需要看看RaisePropertyChanged – Paparazzi

回答

3

因爲您的財產SelectedVehicle是引用類型。
當你結合SelectedValueViewModel.SelectedVehicle
組合框比較有限集合中的對象的SelectedVehicle

反對通過調用.Equals方法,它在默認情況下比較引用,如果兩個對象引用相同的內存地址返回true比較發生

由於選定的項目沒有出現,我假定參考SelectedVehicle不在集合Vehicles

您可以覆蓋類Vehicle中的Equals方法以通過某些屬性進行比較。在你的情況下,這將是最短的方式。
使用鑑於你的第二個方法與SelectedItem並在Vehicle類中重寫Equals方法:

public override bool Equals(Person compareTo) 
{ 
    if (compareTo == null) 
     return false; 
    return (this.ID == compareTo.ID); 
} 

或者我更喜歡未來的做法,確定該車爲ValueMemberPath

<ComboBox DisplayMemberPath="Number" 
     ValueMemberPath="Number" 
     ItemsSource="{Binding Vehicles, UpdateSourceTrigger=PropertyChanged}" 
     SelectedValue="{Binding SelectedVehicle, UpdateSourceTrigger=PropertyChanged}" /> 

在視圖模型更
使用屬性

public Int32 SelectedVehicleNumber 
{ 
    get { return PrimaryModel.Vehicle.Number; } 
    set 
    { 
     if (PrimaryModel.Vehicle.Number != value) 
     { 
      PrimaryModel.Vehicle = New Vehicle(value);//Create instance by selected value 
      RaisePropertyChanged("SelectedVehicle"); 
     } 
    } 
} 

並與KeyedCollection

+1

你說得對。我決定使用Equals方法。謝謝。 – mosquito87

1

嘗試綁定SelectedItem而不是SelectedValue

此外,請確保Vehicles屬性之前SelectedVehicle屬性。

+0

對不起,忘了提及我已經根據這個答案試過了@ http://stackoverflow.com/questions/19632270/binding- combobox-selecteditem-using-mvvm ...查看我的更新問題。 – mosquito87

0

我做了一個小例子,就這一個更多的辦法:

我有這個簡單的觀點:

<Window x:Class="ComboSelectedItemBinding.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:ComboSelectedItemBinding" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Grid.DataContext> 
     <local:ViewModel/> 
    </Grid.DataContext> 
    <StackPanel> 
     <ComboBox ItemsSource="{Binding vehicles, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding VehicleSelected}" DisplayMemberPath="Name" SelectedIndex="0" VerticalAlignment="Top"/> 
     <TextBox x:Name="VehName" MinWidth="120" Margin="80,10" /> 
     <Button Content="Change selection" Command="{Binding ChangeCommand}" CommandParameter="{Binding ElementName=VehName, Path=Text}" Margin="10" Width="150"/> 
    </StackPanel> 

</Grid> 

這是模型:

public class Vehicle : INotifyPropertyChanged 
{ 
    private string _Name; 

    public string Name 
    { 
     get { return _Name; } 
     set { _Name = value; } 
    } 


    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 

    public void OnPropertyChanged(string propertyName) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

The ViewModel:

public class ViewModel : DependencyObject 
{ 
    public ObservableCollection<Vehicle> vehicles { get; set; } 

    public ICommand ChangeCommand { get; set; } 


    public Vehicle VehicleSelected 
    { 
     get { return (Vehicle)GetValue(VehicleSelectedProperty); } 
     set { SetValue(VehicleSelectedProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for VehicleSelected. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty VehicleSelectedProperty = 
     DependencyProperty.Register("VehicleSelected", typeof(Vehicle), typeof(ViewModel), new PropertyMetadata(null)); 



    public ViewModel() 
    { 
     vehicles = new ObservableCollection<Vehicle>(); 
     Vehicle veh1 = new Vehicle() { Name = "V1" }; 
     Vehicle veh2 = new Vehicle() { Name = "V2" }; 
     Vehicle veh3 = new Vehicle() { Name = "V3" }; 
     Vehicle veh4 = new Vehicle() { Name = "V4" }; 

     vehicles.Add(veh1); 
     vehicles.Add(veh2); 
     vehicles.Add(veh3); 
     vehicles.Add(veh4); 

     ChangeCommand = new ChangeCommand(this); 
    } 
} 

和命令的按鈕:

public class ChangeCommand : ICommand 
{ 
    public ViewModel _vm = null; 

    public ChangeCommand(ViewModel vm) 
    { 
     _vm = vm; 
    } 
    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     _vm.VehicleSelected = _vm.vehicles.First(name => name.Name.Equals(parameter.ToString())); 
    } 
} 

爲了使該組合框,你必須保持它的邊界集合中的一個對象的引用的變化。爲了實現這一點,我已經添加了根據車輛名稱改變選擇的方式。使用車輛名稱,您可以搜索列表中的參考項目,並將其設置爲SelectedItem,該項目被定義爲DependencyProperty,只是做一個小的變化。