wpf多列组合框将选择绑定到itemssource集合的子类

时间:2014-04-17 21:55:38

标签: wpf binding combobox subclass selecteditem

假设我们有以下型号:

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事件以刷新到组合框。

有没有其他方法可以实现这一目标,或者我错过了什么?

非常感谢帮助。

1 个答案:

答案 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}">