我有一个ViewModel,它有一个集合和一个属性,表示集合中的选定值。在我看来,这是在ComboBox中显示的。当“填充”我的ViewModel时,我的视图中不会显示所选项目。
我的ViewModel
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
的setter,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 :(得分:3)
因为您的媒体资源SelectedVehicle
是参考类型
将SelectedValue
绑定到ViewModel.SelectedVehicle
时
组合框将有界Collection的对象与SelectedVehicle
通过调用.Equals
方法进行比较,默认情况下比较引用并在两个对象引用相同内存地址时返回true
由于未显示所选项目,因此我假设SelectedVehicle
的参考不在集合Vehicles
中。
您可以覆盖类Equals
中的Vehicle
方法,以便按某些属性进行比较。在你的情况下,这将是最短的方式
通过SelectedItem
使用您的第二种方法,并在Equals
类中覆盖Vehicle
方法:
public override bool Equals(Person compareTo)
{
if (compareTo == null)
return false;
return (this.ID == compareTo.ID);
}
或者我更喜欢下一个方法
使用标识Vehicle ValueMemberPath
<ComboBox DisplayMemberPath="Number"
ValueMemberPath="Number"
ItemsSource="{Binding Vehicles, UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding SelectedVehicle, UpdateSourceTrigger=PropertyChanged}" />
在ViewModel中
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");
}
}
}
的另一种方法
答案 1 :(得分:1)
尝试绑定SelectedItem
而不是SelectedValue
。
此外,请确保在 Vehicles
属性之前设置了SelectedVehicle
属性。
答案 2 :(得分: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 ));
}
}
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,只是为了做一个小的变化。