WPF ComboBox SelectedItem动态绑定

时间:2017-06-07 16:53:12

标签: wpf xaml combobox binding converter

我想将ComboBox的SelectedItem绑定到ViewModel中ObservableCollection的特定项目。

在ViewModel中,我有一个ObservableCollection属性:

Public Property SourceList As ObservableCollection(Of CustomItem)

然后我有这两个自定义类

Public Class CustomItem 
    Public Property Code As String
    Public Property Source As List(Of CustomValue)
    Public Property Selection As Object
End Class

Public Class CustomValue 
    Public Property Id As Integer
    Public Property Desc As String
End Class

XAML中的ComboBox

<Border Tag="10">
    <ComboBox DisplayMemberPath="Desc">
            <ComboBox.ItemsSource>
                <MultiBinding Converter="{StaticResource comboSourceConverter}">
                    <Binding Path="SourceList"/>
                    <Binding Path="Tag" RelativeSource="{RelativeSource AncestorLevel=1, Mode=FindAncestor, AncestorType=Border}" />
                </MultiBinding>
            </ComboBox.ItemsSource>
        </ComboBox>
</Border>

我用来设置ItemsSource的转换器,它可以正常工作。

Public Function Convert(values() As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IMultiValueConverter.Convert
    If values(0) IsNot Nothing AndAlso values(1) IsNot Nothing Then
        Return DirectCast(values(0), ObservableCollection(Of CustomItem)).Where(Function(x) x.Code = CStr(values(1))).First().Source
    End If
    Return Binding.DoNothing
End Function

Public Function ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
    Throw New NotImplementedException
End Function

我尝试为SelectedItem做类似的事情。 在XAML中:

<Border Tag="10">
<ComboBox DisplayMemberPath="Desc">
        <ComboBox.ItemsSource>
            <MultiBinding Converter="{StaticResource comboSourceConverter}">
                <Binding Path="SourceList"/>
                <Binding Path="Tag" RelativeSource="{RelativeSource AncestorLevel=1, Mode=FindAncestor, AncestorType=Border}" />
            </MultiBinding>
        </ComboBox.ItemsSource>
        <ComboBox.SelectedItem>
            <MultiBinding Converter="{StaticResource comboSourceConverter}">
                <Binding Path="SourceList"/>
                <Binding Path="Tag" RelativeSource="{RelativeSource AncestorLevel=1, Mode=FindAncestor, AncestorType=Border}" />
            </MultiBinding>
        </ComboBox.SelectedItem>
    </ComboBox>

转换器返回在ComboBox中选择的正确值,但这样会在SourceList属性上引发Set方法,因为它是声明为Multibinding中第一个Path的那个。

Public Function Convert(values() As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IMultiValueConverter.Convert
    If values(0) IsNot Nothing AndAlso values(1) IsNot Nothing Then
        Return DirectCast(values(0), ObservableCollection(Of CustomItem)).Where(Function(x) x.Code = CStr(values(1))).First().Selection 
End If
    Return Binding.DoNothing
End Function

Public Function ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
    Return New Object(){value} 
End Function

手动设置绑定一切正常,但我希望尽可能通过转换器完成所有操作。

Dim _item As CustomItem = SourceList.Where(Function(x) x.Code = Border.Tag).FirstOrDefault()
Dim _binding = New Binding("Selection")
_binding.Mode = BindingMode.TwoWay
_binding.Source = _item 
ComboBox.SetBinding(ComboBox.SelectedItemProperty, _binding)

1 个答案:

答案 0 :(得分:1)

你应该让XAML为你做更多艰苦的工作。获取CustomItem一次,然后绑定到它的属性,不用担心。

<Border DataContext="{Binding SourceList[10]}">
    <ComboBox 
        DisplayMemberPath="Desc"
        ItemsSource="{Binding Source}"
        SelectedItem="{Binding Selection}"
        />
</Border>

这意味着什么。我们致电SourceList[10] itemX

var itemX = SourceList[10];
  • ComboBox将显示CustomValue中找到的itemX.Source集合。

  • ComboBox会将其选定的项目分配给itemX.Selection

或者更好,这个。我不确定这是你正在做的事情的背景,但它说明了思考这些事情的方式:

<ItemsControl ItemsSource="{Binding SourceList}">
    <ItemsControl.ItemsTemplate>
        <DataTemplate>
            <!-- 
            Inside the DataTemplate, the DataContext will be one item 
            from SourceList.
            -->
            <Border>
                <ComboBox 
                    DisplayMemberPath="Desc"
                    ItemsSource="{Binding Source}"
                    SelectedItem="{Binding Selection}"
                    />
            </Border>
        </DataTemplate>
    </ItemsControl.ItemsTemplate>
</ItemsControl>