65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (6投票s)

2009年5月27日

CPOL

2分钟阅读

viewsIcon

34037

downloadIcon

265

一种通过使用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 设计模式。 我有一个位置实体,其类图如下

LocationEntity.jpg

模型

模型描述了数据源,在我的例子中是以下内容

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 中,它的 ItemSourceCompanyLocations (记住我在 ViewModel 中公开的用于获取所有 Location 实体数据的属性) ,还有一个名为 CompanyLocationTemplateItemTemplate

<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日:首次发布
© . All rights reserved.