[WPF] 真的不用寫程式也能藉由資料改變外觀 - 利用DataTemplate.Triggers

我們常常透過資料繫結來呈現各種不同的資料,但是隨著使用者介面的進步,如果能隨著資料的內容改變資料呈現的方式的話,那對使用者來說將會更加的直覺,也可以讓一成不變的畫面增添許多更豐富的元素。
這次就用一個範例,來跟各位分享在WPF中,不需要撰寫一行的CodeBehind程式碼(不過要寫XAML啦~),就能讓呈現資料的介面會隨著我們訂義好的條件以及資料的內容自動採取不同的顯示方式。

 

我們常常透過資料繫結來呈現各種不同的資料,但是隨著使用者介面的進步,如果能隨著資料的內容改變資料呈現的方式的話,那對使用者來說將會更加的直覺,也可以讓一成不變的畫面增添許多更豐富的元素。

這次就用一個範例,來跟各位分享在WPF中,不需要撰寫一行的CodeBehind程式碼(不過要寫XAML啦~),就能讓呈現資料的介面會隨著我們訂義好的條件以及資料的內容自動採取不同的顯示方式。

先來看看實際的範例程式吧:

(*若無法正常瀏覽本文WPF版範例,煩請參考[Windows7]使用IE9、FireFox與Chrome瀏覽WPF Browser Application(.XBAP)的方式一文調整瀏覽器設定,本範例的圖片皆為外連,若圖片無法正常顯示,請試看看瀏覽器的重新整理功能)

光看上面的範例應該是看不出什麼特別之處,就容我來講解一下我做了什麼吧!

首先,我透過Expression Blend產生了以下的範例資料:

SampleDataSource.xaml

<SampleData:SampleDataSource xmlns:SampleData="clr-namespace:Expression.Blend.SampleData.SampleDataSource">
	<SampleData:SampleDataSource.Collection>
		<SampleData:Item Name="麥可傑克森" Sex="True" IsRip="True" 
			ImageUrl="http://autoproducts.aape.biz/attachments/news_pic/12488366864a6fbc4ed0291.jpg"/>
		<SampleData:Item Name="林志玲" Sex="False" IsRip="False" 
			ImageUrl="http://m1.aboluowang.com/ent/data/uploadfile/201009/20100907014207501.jpg"/>
		<SampleData:Item Name="張國榮" Sex="True" IsRip="True" 
			ImageUrl="http://blog.66wz.com/attachments/2009/04/216330_2009040722384511HSg.jpg"/>
		<SampleData:Item Name="劉德華" Sex="True" IsRip="False" 
			ImageUrl="http://gb.cri.cn/mmsource/images/2008/12/03/rb081203056.jpg"/>
   		<SampleData:Item Name="張惠妹" Sex="False" IsRip="False" 
			ImageUrl="http://news.xinhuanet.com/audio/2007-06/21/xinsrc_1420604210933578612221.jpg"/>
		<SampleData:Item Name="金城武" Sex="True" IsRip="False" 
			ImageUrl="http://big5.sznews.com/fashion/images/attachement/jpg/site3/20080724/001e4f9d7beb09f279ae19.jpg"/>
		<SampleData:Item Name="許瑋倫" Sex="False" IsRip="True" 
			ImageUrl="http://images.sjspy.com/6/127363394127485.jpg"/>	
		<SampleData:Item Name="張學友" Sex="True" IsRip="False" 
			ImageUrl="http://a0.att.hudong.com/64/98/01300001212425130362984330814.jpg"/>
		<SampleData:Item Name="梅豔芳" Sex="False" IsRip="True" 
			ImageUrl="http://blog.m1905.com/attachment/200912/29/920798_1262063403vQvD.jpg"/>
		<SampleData:Item Name="郭富城" Sex="True" IsRip="False" 
			ImageUrl="http://pica.nipic.com/2008-01-22/200812212461285_2.jpg"/>
		<SampleData:Item Name="女神卡卡" Sex="False" IsRip="False" 
			ImageUrl="http://tw.music.yahoo.com/img/1245054812.jpg"/>
		<SampleData:Item Name="黃家駒" Sex="True" IsRip="True" 
			ImageUrl="http://i3.ce.cn/ent/zt/2009/qwqs/qwqsyh/200907/28/W020090728500959016971.jpg"/>
	</SampleData:SampleDataSource.Collection>
</SampleData:SampleDataSource>

接著呢,我想透過一個ListBox來呈現這些資料,並且我希望每個項目的背景色會依照性別的不同而改變,而且若該資料中的明星已經逝世的話,我希望在名字的旁邊會出現一個標示為逝世的小圖示。

就讓我先跳過怎麼把透過修改ListBox.ItemsTemplate的方式來讓每筆資料以上述方式來呈現的部份,直接切入這次的主題 - DataTemplate.Triggers!!

我們除了可以透過將自訂的DataTemplate指定給ListBox的ItemsTemplate屬性來決定資料的呈現方式之外,還可以更進一步的在DataTemplate中加入觸發器,一旦繫結資料符合我們所設定的條件,就可以在執行期動態的改變DateTemplate中項目的屬性

而DataTemplate中可以使用的Triggers不只一種,不過因為這次我們只需要透過資料的內容來當作觸發條件,所以就只使用到DataTrigger而已喔!!

在XAML中DataTemplate.Triggers的基本寫法如下:


<DataTemplate.Triggers>
	<!--這個區塊可以放一至多個不同的Trigger-->	
	<DataTrigger Binding="{Binding Path=要被判斷值的屬性}" Value="符合條件的值">
		<DataTrigger.Setters>
			<!--這邊可以放多個Setter,當符合條件時,用來改變物件的屬性值-->		
			<Setter Property="屬性名稱" Value="符合條件時的屬性值" TargetName="符合條件時要被修改的物件名稱" />
			<!-- 更多的Setter -->
		</DataTrigger.Setters>
	</DataTrigger>
        <!-- 更多的Trigger -->
</DataTemplate.Triggers>

再來看看我寫的實例,應該就會更有Fu喔!!

Page1.xaml

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
		xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
		xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
		xmlns:ee="http://schemas.microsoft.com/expression/2010/effects"
		xmlns:local="clr-namespace:Wpf_DataTemplateWithTrigger" x:Class="Wpf_DataTemplateWithTrigger.Page1"
		mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="800" ShowsNavigationUI="False" Title="Page1">
	<Page.Resources>
		<DataTemplate x:Key="ItemTemplate">
			<Border x:Name="border" HorizontalAlignment="Left" Height="200" VerticalAlignment="Top" Width="220"
					CornerRadius="10" Background="#FF646464" Margin="10">
				<Grid>
					<Grid.RowDefinitions>
						<RowDefinition />
					</Grid.RowDefinitions>
					<Image x:Name="image" Source="{Binding ImageUrl}" HorizontalAlignment="Stretch"
							VerticalAlignment="Stretch" Margin="10,10,10,40" Stretch="UniformToFill"
							Clip="M0,10 C0,4.4771525 4.4771525,0 10,0 L190,0 C195.52285,0 200,4.4771525 200,10 L200,140 C200,
						          145.52285 195.52285,150 190,150 L10,150 C4.4771525,150 0,145.52285 0,140 z" />
					<local:RipIcon x:Name="ripIcon" HorizontalAlignment="Right" VerticalAlignment="Bottom"
							Margin="0,0,5,5" Visibility="Collapsed" Grid.Row="1" Opacity="0.5" />
					<TextBlock x:Name="txtName" Text="{Binding Name}" FontSize="18.667" Grid.Row="1"
							VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,8"
							Foreground="#FF333333" />
				</Grid>
			</Border>
			<DataTemplate.Triggers>
				<DataTrigger Binding="{Binding Sex}" Value="False">
					<Setter TargetName="border" Property="Background" Value="Pink" />
				</DataTrigger>
				<DataTrigger Binding="{Binding Sex}" Value="True">
					<Setter TargetName="border" Property="Background" Value="SkyBlue" />
				</DataTrigger>
				<DataTrigger Binding="{Binding IsRip}" Value="True">
					<Setter TargetName="ripIcon" Property="Visibility" Value="Visible" />
				</DataTrigger>
			</DataTemplate.Triggers>
		</DataTemplate>
		<ItemsPanelTemplate x:Key="ItemsPanelTemplate">
			<WrapPanel />
		</ItemsPanelTemplate>
	</Page.Resources>
	<Border BorderThickness="2" CornerRadius="10" Margin="10" Background="White" BorderBrush="#FF646464"
			DataContext="{Binding Source={StaticResource SampleDataSource}}">
		<Grid x:Name="LayoutRoot" Background="Transparent">
			<Grid.RowDefinitions>
				<RowDefinition Height="40" />
				<RowDefinition />
				<RowDefinition Height="Auto" />
			</Grid.RowDefinitions>
			<TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="WPF DateTemplate Trigger 範例"
					VerticalAlignment="Center" FontSize="26.667" FontWeight="Bold" Foreground="#FF646464" />
			<Rectangle Fill="#FF646464" Height="2" Margin="10,0" VerticalAlignment="Bottom" />
			<ListBox Margin="10,10,10,30" Grid.Row="1" ItemTemplate="{DynamicResource ItemTemplate}"
					ItemsSource="{Binding Collection}" ItemsPanel="{DynamicResource ItemsPanelTemplate}"
					ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
			<TextBlock x:Name="textBlock" HorizontalAlignment="Right" TextWrapping="Wrap"
					Text="本範例中使用之明星圖片均為網路上擷取而來,僅供教學範例之用,若有侵權,煩請告知。" 
					VerticalAlignment="Bottom" Grid.Row="1"
					Margin="0,0,10,5" Opacity="0.75" />
		</Grid>
	</Border>
</Page>

CodeBehind呢!!?免!!一行都不用寫~~是不是比想像中來得簡單呢!!?

最後,歡迎有興趣的朋友請自行下載專案原始碼回去研究喔~