ComboBox ItemTemplate仅在下拉列表中工作 [英] ComboBox ItemTemplate only working in dropdown
问题描述
< ComboBox ItemsSource ={Binding GroupBoxes}SelectedValue ={Binding SelectedGroupBox}>
< ComboBox.ItemTemplate>
< DataTemplate>
< TextBlock Text ={Binding Name}/>
< / DataTemplate>
< /ComboBox.ItemTemplate>
< / ComboBox>
GroupBoxes和SelectedGroupBox是ObservableCollection和GroupBox类型的DependencyProperties。
绑定工作 - 控件名称显示在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(
(GroupWindow),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
ComboBox,由于一些非常复杂的原因,暴露一个名为SelectionBoxItem的只读属性。 ComboBox模板中的内容呈现器绑定此属性。它是SelectionBoxItem,暴露非UI元素的字符串表示,允许您查看所选的值。使用此属性将阻止内容提供者使用数据模板。这就是为什么模板应用于下拉列表而不是所选项目的原因。以下是导致此问题的默认ComboBox模板的部分:
< ContentPresenter IsHitTestVisible =false
=8,1,1,1
Content ={TemplateBinding SelectionBoxItem}
ContentTemplate ={TemplateBinding SelectionBoxItemTemplate}
ContentTemplateSelector ={TemplateBinding ItemTemplateSelector}
VerticalAlignment ={TemplateBinding VerticalContentAlignment}
HorizontalAlignment ={TemplateBinding HorizontalContentAlignment}
SnapsToDevicePixels ={TemplateBinding SnapsToDevicePixels}/>然而,您可以创建自己的ComboBox样式,覆盖默认的ContentPresenter,并使用SelectedItem而不是SelectionBoxItem,并且ItemTemplate而不是SelectionItemBoxTemplate。这将解决问题。
I am trying to show a ComboBox whose ItemsSource is a collection of Controls (it is part of a PropertyGrid, the ComboBox should display the names of the controls, and the user should be able to select one of the controls). Here is an extremely simplified reproduction of the problem:
<ComboBox ItemsSource="{Binding GroupBoxes}" SelectedValue="{Binding SelectedGroupBox}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
GroupBoxes and SelectedGroupBox are DependencyProperties of type ObservableCollection and GroupBox.
The Bindings work - the control names are displayed in the ComboBox-DropDown, and if I select a different item I can see that the SelectedGroupBox property is updated correctly. The problem: the selected item is never displayed in the ComboBox. Setting the SelectedGroupBox property from code also works as expected - the ComboBox raises SelectionChanged and its SelectedValue is correct, but it still doesn't display the current value.
If I do the exact same thing with any other type of class, everything works as expected.
Searching for an answer I came across many posts from people having similar sounding problems, but almost all of them were Binding proplems which is not the case here.
Edit:
To simplify trying it out, here's the code behind. Just drop the above XAML in a new Window, and the code below in the code behind.
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
解决方案 The ComboBox, for some very complex reasons exposes a read-only property called SelectionBoxItem. The content presenter in the ComboBox template binds on this property. It is the SelectionBoxItem that exposes the string representation of non-UI elements allowing you to see the selected value. The use of this property is what prevents the content presenter from using data templates. This is why the template applies to the drop down but not the selected item. Here is the part of the default ComboBox template causing the issue:
<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}"/>
You can however create your own ComboBox style that overrides the default ContentPresenter and uses the SelectedItem instead of SelectionBoxItem and ItemTemplate instead of SelectionItemBoxTemplate. This will resolve the issue.
这篇关于ComboBox ItemTemplate仅在下拉列表中工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!