WPF组合框-选择值时显示不同的内容

WPF组合框-选择值时显示不同的内容,wpf,data-binding,combobox,Wpf,Data Binding,Combobox,我需要完成的是一个显示人的组合框。当您展开下拉列表时,它会显示FirstName和LastName,但是当您选择一个人时,组合框中显示的值应该只是这个人的名字 我有以下ItemTemplate: <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Firs

我需要完成的是一个显示人的组合框。当您展开下拉列表时,它会显示FirstName和LastName,但是当您选择一个人时,组合框中显示的值应该只是这个人的名字

我有以下ItemTemplate:

<ComboBox.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding FirstName}" />
            <TextBlock Text=" " />
            <TextBlock Text="{Binding LastName}" />
        </StackPanel>
    </DataTemplate>
</ComboBox.ItemTemplate>

当选择一个项目时,我还应该做什么才能只显示第一个名称

谢谢

编辑
稍微改变了这个问题:如果我有一个人的照片,当一个人被选中时,我不想只显示他的名字,我只想显示照片,那该怎么办。换句话说,我怎么能有两个单独的模板——一个用于下拉列表,一个用于所选项目?

我知道了。我只需要在组合框中添加以下内容:

IsEditable="True" IsReadOnly="True" TextSearch.TextPath="FirstName"

在DataTemplate上放置触发器。触发器应该检查IsSelected属性(DataTemplate需要设置TargetType才能工作)。如果选中该选项,则可以将文本块的可见性设置为“折叠”,并将图像的可见性设置为“可见”。如果未选中,则执行相反的操作。

以下是解决方案:

    <ComboBox>
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <ContentControl x:Name="content" Content="{Binding}" ContentTemplate="{StaticResource ComplexTemplate}"/>
                </StackPanel>
                <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ComboBoxItem}}" Value="{x:Null}">
                        <Setter TargetName="content" Property="ContentTemplate" Value="{StaticResource SimpleTemplate}"/>
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

基本上,您可以在这里再创建一层DataTemplate。ComboBox的ItemTemplate始终保持不变。但模板中的内容会根据您感兴趣的条件进行调整

区分下拉组合框项和选定区域组合框项的诀窍在于,选定区域并不是真正包含在ComboBoxItem对象中,它是combobox控件本身的一部分。因此ComboBoxItem的FindAncestor返回null,我们在上面的触发器中使用它。

另一个选项是使用而不是。我一直在用下面的方法

ComboBoxItemTemplateSelector
源于
DataTemplateSelector
,具有两个附加属性,
SelectedTemplate
DropDownTemplate
。然后我们从Xaml中设置数据模板,如下所示

<ComboBox ItemsSource="{Binding Persons}"
          ItemTemplateSelector="{StaticResource ComboBoxItemTemplateSelector}">
    <ts:ComboBoxItemTemplateSelector.SelectedTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding FirstName}" />
        </DataTemplate>
    </ts:ComboBoxItemTemplateSelector.SelectedTemplate>
    <ts:ComboBoxItemTemplateSelector.DropDownTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding FirstName}" />
                <TextBlock Text=" " />
                <TextBlock Text="{Binding LastName}" />
            </StackPanel>
        </DataTemplate>
    </ts:ComboBoxItemTemplateSelector.DropDownTemplate>
</ComboBox>
可在此处下载使用此功能的小型演示项目:

我也在这里发了一篇关于这个的短文:。它还显示了做同样事情的另一种显而易见的方法,但是在
ComboBoxItemTemplateSelector
中使用属性而不是附加属性

哦,还有我的父母。每个人似乎都有自己的实现,但无论如何,这是我正在使用的一个

public static class DependencyObjectExtensions
{
    public static T GetVisualParent<T>(this DependencyObject child) where T : Visual
    {
        while ((child != null) && !(child is T))
        {
            child = VisualTreeHelper.GetParent(child);
        }
        return child as T;
    }
}
公共静态类DependencyObjectExtensions
{
公共静态T GetVisualParent(此DependencyObject子对象),其中T:Visual
{
while((child!=null)&&&!(child是T))
{
child=visualtreeheloper.GetParent(child);
}
返回子对象作为T;
}
}
我使用了下一种方法

 <UserControl.Resources>
    <DataTemplate x:Key="SelectedItemTemplate" DataType="{x:Type statusBar:OffsetItem}">
        <TextBlock Text="{Binding Path=ShortName}" />
    </DataTemplate>
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
    <ComboBox DisplayMemberPath="FullName"
              ItemsSource="{Binding Path=Offsets}"
              behaviors:SelectedItemTemplateBehavior.SelectedItemDataTemplate="{StaticResource SelectedItemTemplate}"
              SelectedItem="{Binding Path=Selected}" />
    <TextBlock Text="User Time" />
    <TextBlock Text="" />
</StackPanel>

行为呢

public static class SelectedItemTemplateBehavior
{
    public static readonly DependencyProperty SelectedItemDataTemplateProperty =
        DependencyProperty.RegisterAttached("SelectedItemDataTemplate", typeof(DataTemplate), typeof(SelectedItemTemplateBehavior), new PropertyMetadata(default(DataTemplate), PropertyChangedCallback));

    public static void SetSelectedItemDataTemplate(this UIElement element, DataTemplate value)
    {
        element.SetValue(SelectedItemDataTemplateProperty, value);
    }

    public static DataTemplate GetSelectedItemDataTemplate(this ComboBox element)
    {
        return (DataTemplate)element.GetValue(SelectedItemDataTemplateProperty);
    }

    private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var uiElement = d as ComboBox;
        if (e.Property == SelectedItemDataTemplateProperty && uiElement != null)
        {
            uiElement.Loaded -= UiElementLoaded;
            UpdateSelectionTemplate(uiElement);
            uiElement.Loaded += UiElementLoaded;

        }
    }

    static void UiElementLoaded(object sender, RoutedEventArgs e)
    {
        UpdateSelectionTemplate((ComboBox)sender);
    }

    private static void UpdateSelectionTemplate(ComboBox uiElement)
    {
        var contentPresenter = GetChildOfType<ContentPresenter>(uiElement);
        if (contentPresenter == null)
            return;
        var template = uiElement.GetSelectedItemDataTemplate();
        contentPresenter.ContentTemplate = template;
    }


    public static T GetChildOfType<T>(DependencyObject depObj)
        where T : DependencyObject
    {
        if (depObj == null) return null;

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            var child = VisualTreeHelper.GetChild(depObj, i);

            var result = (child as T) ?? GetChildOfType<T>(child);
            if (result != null) return result;
        }
        return null;
    }
}
public静态类SelectedItemTemplateBehavior
{
公共静态只读从属属性SelectedItemDataTemplateProperty=
DependencyProperty.RegisterAttached(“SelectedItemDataTemplate”、typeof(DataTemplate)、typeof(SelectedItemTemplateBehavior)、new PropertyMetadata(default(DataTemplate)、PropertyChangedCallback));
公共静态void SetSelectedItemDataTemplate(此UIElement元素,DataTemplate值)
{
element.SetValue(SelectedItemDataTemplateProperty,value);
}
公共静态数据模板GetSelectedItemDataTemplate(此组合框元素)
{
return(DataTemplate)元素.GetValue(SelectedItemDataTemplateProperty);
}
私有静态无效属性ChangedCallback(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
var uiElement=d作为组合框;
if(e.Property==SelectedItemDataTemplateProperty&&uiElement!=null)
{
uiElement.Loaded-=UiElementLoaded;
更新选择模板(uiElement);
uiElement.Loaded+=UiElementLoaded;
}
}
静态void UiElementLoaded(对象发送器、路由目标)
{
UpdateSelectTemplate((组合框)发送方);
}
私有静态void updateSelectTemplate(组合框uiElement)
{
var contentPresenter=GetChildOfType(uiElement);
if(contentPresenter==null)
返回;
var template=uiElement.GetSelectedItemDataTemplate();
contentPresenter.ContentTemplate=模板;
}
公共静态T GetChildOfType(DependencyObject depObj)
其中T:DependencyObject
{
if(depObj==null)返回null;
for(int i=0;i

工作得很有魅力。我不太喜欢这里加载的事件,但如果您愿意,可以修复它。

这解决了我最初的问题,但我对它做了一点修改。当选择一个项目时,我怎么能只显示图片而不是名字?谢谢你,需要一个简单的解决方案。喜欢它,这正是我想要的!谢谢这是有道理的,因为在组合框中只选择了一个项目。好主意。感谢这个令人敬畏的解决方案。唯一的问题是,它导致WPF由于从未找到祖先而引发绑定错误。有点晚了,但在我看来是相关的。此处描述了与下面提到的完全不同的解决方案:。没有自定义代码,也可以很好地工作。
public static class SelectedItemTemplateBehavior
{
    public static readonly DependencyProperty SelectedItemDataTemplateProperty =
        DependencyProperty.RegisterAttached("SelectedItemDataTemplate", typeof(DataTemplate), typeof(SelectedItemTemplateBehavior), new PropertyMetadata(default(DataTemplate), PropertyChangedCallback));

    public static void SetSelectedItemDataTemplate(this UIElement element, DataTemplate value)
    {
        element.SetValue(SelectedItemDataTemplateProperty, value);
    }

    public static DataTemplate GetSelectedItemDataTemplate(this ComboBox element)
    {
        return (DataTemplate)element.GetValue(SelectedItemDataTemplateProperty);
    }

    private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var uiElement = d as ComboBox;
        if (e.Property == SelectedItemDataTemplateProperty && uiElement != null)
        {
            uiElement.Loaded -= UiElementLoaded;
            UpdateSelectionTemplate(uiElement);
            uiElement.Loaded += UiElementLoaded;

        }
    }

    static void UiElementLoaded(object sender, RoutedEventArgs e)
    {
        UpdateSelectionTemplate((ComboBox)sender);
    }

    private static void UpdateSelectionTemplate(ComboBox uiElement)
    {
        var contentPresenter = GetChildOfType<ContentPresenter>(uiElement);
        if (contentPresenter == null)
            return;
        var template = uiElement.GetSelectedItemDataTemplate();
        contentPresenter.ContentTemplate = template;
    }


    public static T GetChildOfType<T>(DependencyObject depObj)
        where T : DependencyObject
    {
        if (depObj == null) return null;

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            var child = VisualTreeHelper.GetChild(depObj, i);

            var result = (child as T) ?? GetChildOfType<T>(child);
            if (result != null) return result;
        }
        return null;
    }
}