ComboBox ItemTemplate仅在下拉列表中工作

wil*_*ord 18 wpf combobox

我试图显示一个ComboBox,其ItemsSource是一个控件的集合(它是一个PropertyGrid的一部分,ComboBox应该显示控件的名称,用户应该能够选择其中一个控件).这是一个非常简化的问题再现:

<ComboBox ItemsSource="{Binding GroupBoxes}" SelectedValue="{Binding SelectedGroupBox}">
  <ComboBox.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding Name}"/>
    </DataTemplate>
  </ComboBox.ItemTemplate>          
</ComboBox>
Run Code Online (Sandbox Code Playgroud)

GroupBoxes和SelectedGroupBox是ObservableCollection和GroupBox类型的DependencyProperties.

Bindings工作 - 控件名称显示在ComboBox-DropDown中,如果我选择不同的项目,我可以看到SelectedGroupBox属性已正确更新.问题:所选项目永远不会显示在ComboBox中.从代码设置SelectedGroupBox属性也可以按预期工作 - ComboBox引发SelectionChanged并且其SelectedValue是正确的,但它仍然不显示当前值.

如果我对任何其他类型的类做同样的事情,一切都按预期工作.

在寻找答案时,我遇到了许多有类似声音问题的人的帖子,但几乎所有这些都是绑定问题,而这并非如此.

编辑:

为了简化尝试,这里是代码背后的代码.只需将上面的XAML放在一个新窗口中,然后将代码放在后面的代码中.

public MainWindow() {
    InitializeComponent();
    this.DataContext = this;
    this.GroupBoxes = new ObservableCollection<GroupBox>();
    this.GroupBoxes.Add(new GroupBox() { Name = "AAA", Header = "AAA", Height = 100, Background = Brushes.Purple });
    this.GroupBoxes.Add(new GroupBox() { Name = "BBB", Header = "BBB", Height = 100, Background = Brushes.Purple });
    this.GroupBoxes.Add(new GroupBox() { Name = "CCC", Header = "CCC", Height = 100, Background = Brushes.Purple });
    this.GroupBoxes.Add(new GroupBox() { Name = "DDD", Header = "DDD", Height = 100, Background = Brushes.Purple });
    this.GroupBoxes.Add(new GroupBox() { Name = "EEE", Header = "EEE", Height = 100, Background = Brushes.Purple });
}

#region GroupBoxesProperty

public static readonly DependencyProperty GroupBoxesProperty = DependencyProperty.Register(
    "GroupBoxes", typeof(ObservableCollection<GroupBox>), typeof(MainWindow)
);

public ObservableCollection<GroupBox> GroupBoxes {
    get { return (ObservableCollection<GroupBox>)GetValue(GroupBoxesProperty); }
    set { SetValue(GroupBoxesProperty, value); }
}

#endregion

#region SelectedGroupBoxProperty

public static readonly DependencyProperty SelectedGroupBoxProperty = DependencyProperty.Register(
    "SelectedGroupBox", typeof(GroupBox), typeof(MainWindow),
    new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (s, e) => (s as MainWindow).OnSelectedGroupBoxChanged())
);

public GroupBox SelectedGroupBox {
    get { return (GroupBox)GetValue(SelectedGroupBoxProperty); }
    set { SetValue(SelectedGroupBoxProperty, value); }
}

void OnSelectedGroupBoxChanged() {
    Console.WriteLine("selection is now " + this.SelectedGroupBox.Name);
}

#endregion
Run Code Online (Sandbox Code Playgroud)

ici*_*lik 21

由于一些非常复杂的原因,ComboBox公开了一个名为SelectionBoxItem的只读属性.ComboBox模板中的内容呈现器绑定在此属性上.SelectionBoxItem公开了非UI元素的字符串表示,允许您查看所选值.使用此属性会阻止内容呈现器使用数据模板.这就是模板适用于下拉菜单但不适用于所选项目的原因.以下是导致问题的默认ComboBox模板的一部分:

<ContentPresenter IsHitTestVisible="false"
    Margin="8,1,1,1"
    Content="{TemplateBinding SelectionBoxItem}"
    ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
    ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
Run Code Online (Sandbox Code Playgroud)

但是,您可以创建自己的ComboBox样式来覆盖默认的ContentPresenter,并使用SelectedItem而不是SelectionBoxItem和ItemTemplate而不是SelectionItemBoxTemplate.这将解决问题.

  • 很好的答案,很好地解释,你的修复工作完美,谢谢! (2认同)