在WPF Combo中使用DataTemplate、样式和触发器显示多个属性值






4.43/5 (6投票s)
一种通过使用DataTemplate、样式和触发器在WPF Combo中显示多个属性值的方法

引言
最近,我遇到一种情况,需要用实体模型类中公开的多个属性填充一个组合框。 这里我给出一个简单演示如何做到这一点。
一些关键概念
在继续代码解释或如何解决此类问题之前,我想先介绍一些关键概念,通过这些概念,我们不仅可以解决此类问题,还可以解决相同模式的其他一些问题。
样式
这用于为控件提供通用的外观。 创建样式的基本语法如下
<Style x:Key=Akeyname TargetType={x:Type Control Type}>
<Setter Property=APropertyName Value=PropertyValue></Setter>
</Style>
以下列方式从任何控件中使用样式
<Label Name =lbl Style={StaticResource Akeyname}>
数据模板
可以将模板比作一个容器,可用于容纳大量数据。 这意味着,我们可以在数据模板中使用其他控件来保存数据。
执行此操作的基本语法如下
<DataTemplate x:Key=CompanyLocationTemplate>
<Label Name=lbl Content={Binding Path=PropertyName}></Label>
</DataTemplate>
触发器
可以将其视为 if else
语句的替代品。 让我们看一个简单的例子。 假设我有一个按钮。 我想在鼠标悬停和鼠标移出时更改其颜色。 如果我必须使用编程来实现相同的功能,我将编写一些伪代码,如下所示
If Button.IsFocus
Button. Foreground = Red
Else
Button. Background = Green;
使用触发器,可以这样实现:
<datatemplate.triggers>
<datatrigger property="”" value="”True">
<setter targetname="button" property="Foreground " value="Red" />
<setter targetname="button" property="Background" value="Green" />
</datatrigger>
</datatemplate.triggers>
直接进入程序
目标
我的目标是结合我的 Location 实体中公开的各种属性,例如 CompanyName、County、State、City,以及一些自定义的装饰,并将它们显示在组合框中。 我遵循 Model-View-View Model 设计模式。 我有一个位置实体,其类图如下

模型
模型描述了数据源,在我的例子中是以下内容
private void LocationData()
{
_location.Add(new Location { LocationId = 1,CompanyName = "Microsoft",
Country = "India", State = "Karnataka", City = "Bangalore" });
_location.Add(new Location { LocationId = 2, CompanyName = "Oracle",
Country = "USA", State = "North Carolina", City = "Midland" });
_location.Add(new Location { LocationId = 3,
CompanyName = "Sun Micro Systems", Country = "India",
State = "Maharashtra", City = "Bombay" });
_location.Add(new Location { LocationId = 4,
CompanyName = "Robert Bosch", Country = "USA",
State = "Tennessee", City = "Grand Prairie" });
_location.Add(new Location { LocationId = 5,
CompanyName = "IBM", Country = "India",
State = "West Bengal", City = "Calcutta" });
_location.Add(new Location { LocationId = 6,
CompanyName = "Google", Country = "USA",
State = "Ohio", City = "El Paso" });
}
模型-视图
我的 CompanyViewModel
类公开了一个 ObservableCollection
类型的 Location
,名为 CompanyLocations
,它通过名为 LocationList()
的方法保存来自 Location 实体的所有数据
CompanyLocations = new ObservableCollection(_objDataSource.LocationList());
视图
我的视图的整个源或数据上下文是 CompanyViewModel
//The source(i.e. Datacontext) will be the entire CompanyViewModel
private void SourceContext()
{
this.DataContext = _objViewModel;
}
位置数据在 Window Load 事件中加载
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_objViewModel = new CompanyViewModel();
SourceContext();
_objViewModel.LoadData();
}
进入 XAML 部分
我有一个 ComboBox
定义在 StackPanel
中,它的 ItemSource
是 CompanyLocations
(记住我在 ViewModel
中公开的用于获取所有 Location 实体数据的属性) ,还有一个名为 CompanyLocationTemplate
的 ItemTemplate
<ComboBox Height="21" Margin="27,27,30,0" Name="cmbDiplayInformation"
VerticalAlignment="top" ItemsSource="{Binding CompanyLocations}"
ItemTemplate="{StaticResource CompanyLocationTemplate}"/>
CompanyLocationTemplate
定义如下
<DataTemplate x:Key="CompanyLocationTemplate">> <StackPanel Orientation="Horizontal"> <Label Name ="lblCompanyNameHeader" Style="{StaticResource LabelValues}" Content="Company Name:"></Label> <Label Name="lblCompanyName" Style="{StaticResource DataValues}" Content="{Binding Path=CompanyName}"></Label> <Label Name ="lblSeparator1" Style="{StaticResource LabelValues}" Content="is situated in: "></Label> <Label Name="lblCountry" Style="{StaticResource DataValues}" Content="{Binding Path=Country}"></Label> <Label Name ="lblSeparator2" Style="{StaticResource LabelValues}" Content=", in the state:"></Label> <Label Name="lblState" Style="{StaticResource DataValues}" Content="{Binding Path=State}"></Label> <Label Name ="lblSeparator3" Style="{StaticResource LabelValues}" Content=", whose city is:"></Label> <Label Name ="lblCity" Style="{StaticResource DataValues}" Content="{Binding Path=City}"></Label> </StackPanel> <DataTemplate.Triggers> <DataTrigger Binding="{Binding Path=LocationId}" Value="0" <Setter TargetName="lblCompanyNameHeader" Property="Content" Value=""></Setter> <Setter TargetName="lblCompanyName" Property="Content" Value=""></Setter> <Setter TargetName="lblCountry" Property="Content" Value=""></Setter> <Setter TargetName="lblSeparator1" Property="Content" Value=""></Setter> <Setter TargetName="lblState" Property="Content" Value=""></Setter> <Setter TargetName="lblSeparator2" Property="Content" Value=""></Setter> <Setter TargetName="lblCity" Property="Content" Value=""></Setter> </DataTrigger> </DataTemplate.Triggers> </DataTemplate>
最后,样式如下
<Style x:Key="LabelValues" TargetType="{x:Type Label}">
<Setter Property="Foreground" Value="Red"></Setter>
<Setter Property="Background" Value="Yellow"></Setter>
</Style>
<Style x:Key="DataValues" TargetType="{x:Type Label}">
<Setter Property="Foreground" Value="Black"></Setter>
<Setter Property="Background" Value="Cyan"></Setter>
</Style>
输出
公司名称:COMPANYNAME 位于:COUNTRY,在州:STATE,其城市是:CITY。
粗体、大写的词是 Location 实体的属性。
结论
这只是一个关于如何结合 WPF 的数据模板、样式和触发器的小例子,以便我们可以通过最少的代码获得优雅的解决方案。
历史
- 2009年5月27日:首次发布