WPF ComboBox SelectedItem 动态绑定

Posted

技术标签:

【中文标题】WPF ComboBox SelectedItem 动态绑定【英文标题】:WPF ComboBox SelectedItem dynamic binding 【发布时间】:2017-11-09 03:47:48 【问题描述】:

我想将 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 中的组合框

<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 方法,因为它是在多重绑定中声明为第一个 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)

【问题讨论】:

“我尝试为返回 Selection 属性的 SelectedItem 做类似的事情”——请分享您尝试过的完整代码,以及它是如何失败的。 “类似的东西”和“它不起作用”不足以让任何人猜测你做错了什么。 @EdPlunkett 我的错。我更新了我的问题。 【参考方案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 将显示在itemX.Source 中找到的CustomValue 的集合。

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>

【讨论】:

第一个示例中使用的索引器不会获取列表中 index = 10 的项目吗? @FabioL。见更新。我是否猜错了您要对所选项目执行的操作? 我已经测试了第一个解决方案,它就像一个魅力。我不知道你真的可以做到这一点。非常感谢! @FabioL。很高兴为您提供帮助!

以上是关于WPF ComboBox SelectedItem 动态绑定的主要内容,如果未能解决你的问题,请参考以下文章

WPF combobox selectedItem的问题

WPF:为啥我的 ComboBox SelectedItem 不显示?

WPF MVVM ComboBox SelectedItem 或 SelectedValue 不起作用

WPF中ComboBox控件的SelectedItem和SelectedValue的MVVM绑定

WPF Datagrid Combobox SelectedItem 未正确绑定到 Powershell 对象

WPF ComboBox SelectedItem 在 TabControl 开关上设置为 Null