我有一个ComboBox
显示项目列表。我创建了一个转换器,将此对象类型Map到string
值。
<ComboBox ItemsSource="{Binding SelectedDrawing.Icons}" Name="TrackElementSelector" SelectedItem="{Binding SelectedElement}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=., Converter={StaticResource LayoutElementToStringConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
问题是,当我选择/单击ComboBox
中的一个值时,ComboBox
直接呈现SelectedItem
(它是在我的项目中其他地方定义的UserControl
)。例如,想象一下在ComboBox
上单击字符串元素“Button”后看到文字Button
。我不想要这种行为。
为什么这里没有使用ItemTemplate
?ItemTemplate
似乎只在选择某个值之前使用。
我发现了另一个意想不到的结果。当我下拉ComboBox
进行选择时,控件出现在应用程序其他位置的示例就会消失。我想知道是否由于我的代码库中的东西而发生了一些更复杂的事情,或者这是试图在ComboBox
中显示UserControl
对象的所有后果。
2条答案
按热度按时间8cdiaqws1#
您发现了
ComboBox
控件的一个有趣行为。绑定项时,项的呈现方式有时取决于其类型。例如,如果你绑定的项目已经是ComboBoxItem
类型,它将不会创建额外的容器,因为这将是多余的。这也是其他ItemsControl
的常见设计决策。为什么忽略项目模板
但是,您的问题源于
ComboBox
中所选项目的不同特殊处理(关于ContentControl
s)。如果所选项目是这种类型或其任何直接或间接衍生物(如UserControl
),则ComboBox
将使用其Content
,ContentTemplate
和ContentStringFormat
,而不是为ComboBox
本身上的项目定义的ItemTemplate
或ItemStringFormat
,从而忽略ItemTemplate
。实现详情
您可以在
UpdateSelectionBoxItem
方法中的ComboBox
实现中看到这一点:我不知道为什么要这样实现它,但最初的评论表明,这可能是为了处理绑定项已经是
ComboBoxItem
的情况。也许这种行为不是故意的,而是偶然的。解决方案
如果你想改变这种行为,你有这些选项:
1.创建您自己的
ComboBox
自定义实现。1.将项目模板也添加到
UserControl
作为内容模板。虽然它与给定的实现一起工作,但它是一种黑客。
1.创建忽略特殊处理的自定义控件模板。
您将创建默认样式和控件模板的副本,并调整其
ContentPresenter
。默认情况下,它绑定到特殊的SelectionBoxItemTemplate
属性。您可以通过绑定到ItemTemplate
属性来忽略它。1.不要对项使用
ContentControl
或派生类型,而是使用带有 data 项的数据模板作为源,这是预期的,请参见Data Templating Overview。您不应该将UI元素绑定为
ComboBox
的项目源。相反,绑定封装在模型中的数据,并提供合适的数据模板来显示它。数据可以是一个带有Path
属性的Icon
类,甚至可以是一个表示路径的string
。数据模板可以重用您的
UserControl
类型来显示它(如果它被正确实现为使用其数据上下文绑定数据)。这将导致更好的设计,并且很可能也消除对值转换器的需要。此外,它将自动解决您的第二个问题,消失的控件。我强烈建议您使用此选项,因为它不需要对框架元素进行任何自定义,并且更容易执行和维护。
控件为何消失
在WPF中,UI控件被附加到所谓的visual tree,这是用户界面的层次对象图表示。在此图中,每个UI元素示例只能有单个父级。因此,如果你在不同的地方“使用”一个现有的控件,它会被有效地重新分配给相应的父控件,无论它是在同一个还是不同的可视树中(例如,另一个窗口)和 “消失” 从原来的地方。
plicqrtu2#
源集合(
SelectedDrawing.Icons
)不应该包含UIElements
。则不应用ItemTemplate
。UserControl
或Button
应该在ItemTemplate
中定义:源集合应该包含普通的旧CLR对象(POCO),例如:
另请注意,控件的示例在可视树中只能出现 * 一次 *。