C# 带有UserControl列表的组合框中的WPF绑定

C# 带有UserControl列表的组合框中的WPF绑定,c#,wpf,xaml,combobox,user-controls,C#,Wpf,Xaml,Combobox,User Controls,在两个组合框A和B中。 A的项目资源是自定义列表。B的ItemsSource是用户控制列表。 手动设置SelectedItem时,组合框工作正常,但B组合框UI不显示所选项目。(在调试中,SelectedItem的值映射正确,但组合框B的UI不会更改。) A和B之间的所有其他结构都是相同的。原因是什么 MainWindow.xaml ... <ComboBox ItemsSource="{Binding FruitList}" SelectedItem="{Binding Selecte

在两个组合框A和B中。 A的项目资源是自定义列表。B的ItemsSource是用户控制列表。 手动设置SelectedItem时,组合框工作正常,但B组合框UI不显示所选项目。(在调试中,SelectedItem的值映射正确,但组合框B的UI不会更改。) A和B之间的所有其他结构都是相同的。原因是什么

MainWindow.xaml

 ...
<ComboBox ItemsSource="{Binding FruitList}" SelectedItem="{Binding SelectedFruit}"
  DisplayMemberPath="FruitName"  />
<Button Content="Button" HorizontalAlignment="Left"  
VerticalAlignment="Top" Width="75" Click="Button_Click"/>

<ComboBox ItemsSource="{Binding UserControlList}" SelectedItem="{Binding SelectedUserControl}" DisplayMemberPath="ItemName"  />
    <Button Content="Button" HorizontalAlignment="Left"  VerticalAlignment="Top" Width="75" Click="Button_Click2"/>
</Grid>

这不是实现这一目标的好方法。最好为combobox定义ItemTemplate,使其包含UserControl,如下所示:

  <ComboBox ItemsSource="{Binding ItemList}" SelectedItem="{Binding SelectedItem}" >
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <myControls:MyUserControl/>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
既然你问“原因是什么?”:

第二个组合框不显示任何选择的原因是
ComboBox
专门处理
ContentControl
类型的项目。在只读选择框中,用于显示值的不是
ContentControl
,而是
ContentControl
内容。由于
UserControl
ContentControl
,因此
UserControl
的内容显示在选择框内,因此您丢失了
UserControl
的数据上下文;最后,即使
SelectedItem
包含对仍具有有效数据上下文的
UserControl
的引用,也会显示一个空字符串。(据我所知,此行为没有文档记录;但通过检查上的ComboBox代码,特别是UpdateSelectionBoxItem()方法,可以看到它是这样工作的)

通过在第二个组合框上设置
IsEditable=“True”
,您可以看到,如果组合框没有只读选择框,则一切正常

因此,通常应避免将UI元素添加到组合框中,尤其是在使用
DisplayMemberPath
属性的情况下,也就是说,如果您不想实际显示UI元素

@nit的答案中描述了使用非标准外观(例如使用UserControls)显示组合框项目的推荐方法

但是,如果您坚持将
UserControl
项列表传递给组合框,则可以删除
DisplayMemberPath
,并使用类似以下内容:

<ComboBox ItemsSource="{Binding UserControlList}" SelectedItem="{Binding SelectedUserControl}" >
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ItemName}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>
这对于确保只读选择框中有正确的数据上下文是必需的,只读选择框只包含用户控件的内容,而不包含用户控件本身


请注意,在上面的示例中,下拉列表仅包含文本(即项目名称),但选择框将包含完全呈现的用户控件。

谢谢,但xaml例外:无法同时设置DisplayMemberPath和ItemTemplate。。。??删除您不需要的
DisplayMemberPath
it@TzahMama,在删除DisplayMemberPath后,没有异常,但没有工作。是的,删除DisplayMemberPath在我的代码中,“ItemName”表示usercontrol的某个属性,因此我不能划分Item类和MyUserControl类。我误解了你的答案吗?请不要问关于堆栈溢出的重复问题。。。正如你所看到的,他们将被社区关闭。如果您提出了一个问题,并且觉得没有收到满意的答案,那么您可以编辑您的问题以提供进一步的信息(就像您在重复的问题中所做的那样)。这样做会使你的问题回到“最新未回答问题”列表的顶部,因此会吸引更多的注意力。
  <ComboBox ItemsSource="{Binding ItemList}" SelectedItem="{Binding SelectedItem}" >
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <myControls:MyUserControl/>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
public class Item
{
    public string ItemName { get; set; }
}

ObservableCollection<Item> _ItemsList = new ObservableCollection<Item>();
public ObservableCollection<Item> ItemsList 
{
    get
    {
        return _ItemsList ;
    }
    set
    {
        _ItemsList = value;
        OnPropertyChanged();
    }
}
 <TextBlock Text="{Binding ItemName}"></TextBlock>
<ComboBox ItemsSource="{Binding UserControlList}" SelectedItem="{Binding SelectedUserControl}" >
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ItemName}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>
((FrameworkElement) Content).DataContext = this;