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