假设我们有以下型号:
public class MyClass : BaseModel
{
public Item Item1 {get ...; set ...;}
public Item Item2 {get ...; set ...;}
public Item Item3 {get ...; set ...;}
public Item Item4 {get ...; set ...;}
public ObservableCollection<ItemContainer> AllItemContainers {get ...; set ...;}
}
public class ItemContainer : BaseModel
{
public Item Item {get ...; set ...;}
public MyEnum EnumProp {get ...; set ...;}
public byte? SomeProp {get ...; set ...;}
}
public class Item : BaseModel
{
public string Name {get ...; set ...;}
public int Id {get ...; set ...;}
}
所有属性都有INPC(在BaseModel中实现)。
我有4个组合框,显示了Item1,Item2等。对于ItemsSource,我在viewmodel中创建了一个项目列表,我从AllItemContainers
属性创建。
var items = new ObservableCollection<Item>();
foreach (ItemContainer ic in Model.MyClass.AllItemContainers)
{
items.Add(ic.Item);
}
到目前为止它运行良好,组合框显示了正确的Itemname,我可以从下拉列表中选择一个项目并将其分配给Item1属性。
现在,我已经使用了多列组合框,如下所示:
<ComboBox Width="150" Margin="5" HorizontalContentAlignment="Stretch"
ItemsSource="{Binding Model.MyClass.AllItemContainers}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="2" Text="{Binding Path=Item.Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="MinWidth" Value="250"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Width="{Binding ActualWidth, RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type ComboBoxItem}}, Mode=OneTime}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Item.Name}"/>
<TextBlock Grid.Column="1" Text="{Binding Path=EnumProp,
Converter={StaticResource enumToStringConverter}}"
HorizontalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding Path=SomeProp}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
这很好用,我只看到组合框的文本框中的名字,我的下拉列表中有3列。
但是现在我显然无法直接绑定SelectedItem,因为绑定的目标是Item类型,其中SelectedItem的类型为ItemContainer。
<Combobox SelectedItem="Model.MyClass.Item1"/>
我从设置
尝试了很多东西<Combobox SelectedValuePath="Item"/>
编写像这样的转换器
public class ItemContainerToItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var item = value as Item;
var containers = parameter as ObservableCollection<ItemContainer>;
if (item != null && containers != null)
return containers.FirstOrDefault(f => f.Item.Id == item.Id);
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var container = value as ItemContainer;
if (container != null)
return container.Item;
return null;
}
}
我尝试绑定ConverterParameter,但由于它不是DependencyProperty,因此无法绑定。
<ComboBox SelectedItem="{Binding Model.MyClass.Item1,
Converter={StaticResource itemConverter},
ConverterParameter={Binding Model.MyClass.AllItemContainers}}"/>
我现在已经没有想法了,我不想使用SelectionChanged-Event(甚至不使用EventToCommand)并在我的viewmodel中分配值并听取PropertyChanged事件以刷新到组合框。
有没有其他方法可以实现这一目标,或者我错过了什么?
非常感谢帮助。
答案 0 :(得分:0)
您可以尝试设置SelectedValuePath
,而不是SelectedItem
,将SelectedValue
属性绑定到Model / ViewModel中Item
类型的属性:
<ComboBox Width="150" Margin="5" HorizontalContentAlignment="Stretch"
ItemsSource="{Binding AllItemContainers}"
SelectedValuePath="Item"
SelectedValue="{Binding Item1, Mode=TwoWay}">