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

 

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

這次就用一個範例,來跟各位分享在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呢!!?免!!一行都不用寫~~是不是比想像中來得簡單呢!!?

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


 


如果這篇文章對您有幫助,請幫我點一下「我要推薦」、按個讚、或是幫我推到其他平台;您的鼓勵將會是我繼續努力的一大動力!!

若是有任何指教或是需要討論之處,也不用客氣,請在下面留言給我,我將會儘速回覆~

Share | . . . . . . . . . .


Comments

# re: [WPF]真的不用寫程式也能藉由資料改變外觀 - 利用DataTemplate.Triggers
Posted by 小星 on 2011/7/1 下午 02:07 回覆
太感謝啦~不知您是否有寫過在WPF中類似跳出視窗,讓使用者輸入資料後,再記錄下來的程式,例如,一開始時請使用者輸入姓名(而且是在同一頁跳出這個輸入姓名的對話框,使用者輸入完成後,這個對話框會結束),系統需要抓要到這個姓名,並一直存留到程式結束,感謝您一路上的分享~
# re: [WPF]真的不用寫程式也能藉由資料改變外觀 - 利用DataTemplate.Triggers
Posted by Ouch on 2011/7/1 下午 04:07 回覆

to 小星 :
您說的東西應該常常會用到,您可以參考以下兩個連結:

Dialog Boxes Overview

WPF Modal Dialog 

之後透過delegate或是DependencyProperty讓主程式可以取得輸入後的值,並存在一個Global變數中,就可以達到那個效果了~

# re: [WPF]真的不用寫程式也能藉由資料改變外觀 - 利用DataTemplate.Triggers
Posted by 小星 on 2011/7/4 下午 04:00 回覆
謝謝您的資訊都非常有用處~
不知是不是我用巡覽頁面的關係,我依照WPF Modal Dialog的範例,整個UserControl會被鎖住,用一般的Window視窗就可以正常,不知您有遇過這樣的問題嗎?
# re: [WPF]真的不用寫程式也能藉由資料改變外觀 - 利用DataTemplate.Triggers
Posted by Ouch on 2011/7/4 下午 04:31 回覆

to 小星 :
Modal Dialog預設的行為就是會把除了自己本身之外的控制項當成背景並且鎖起來喔!!

如果這樣會造成不便的話,可以參考範例程式碼裡面,針對它的_parent.IsEnabled去做特別的處理。
 

# re: [WPF]真的不用寫程式也能藉由資料改變外觀 - 利用DataTemplate.Triggers
Posted by 小星 on 2011/7/5 上午 11:22 回覆
謝謝,在您的分享下,慢慢的對WPF有些感覺了,雖然還不熟練,我會繼續加油~
# re: [WPF]真的不用寫程式也能藉由資料改變外觀 - 利用DataTemplate.Triggers
Posted by Ouch on 2011/7/5 下午 05:33 回覆

to 小星 :
一起加油吧!!如果還有問題的話請千萬別客氣啊~

# re: [WPF]真的不用寫程式也能藉由資料改變外觀 - 利用DataTemplate.Triggers
Posted by 小星 on 2011/7/6 下午 03:39 回覆
您真是大好人,我又遇到奇怪的問題了~
因為我是用巡覽視窗設計的,想讓使用者可以方便切換頁面,結果發現好像內建設計的上一頁及下一頁,並不是回到上一個頁面,是回到上一個"動作",因為我在page1,xaml有程式邏輯,然後使用this.NavigationService.Navigate(new Uri("page2.xaml", UriKind.Relative))導到page2.xaml,結果在page2.xaml按上一頁,程式會自動再從剛才的程式碼開始動作,又會到page2.xaml,您有遇過這樣的情形嗎?
# re: [WPF]真的不用寫程式也能藉由資料改變外觀 - 利用DataTemplate.Triggers
Posted by Ouch on 2011/7/6 下午 06:06 回覆

to 小星 :
您說的情形我倒是還沒遇到過,不過關於WPF的Navigation,MSDN上的NavigationService ClassNavigation Topologies Overview可能可以參考看看~關於Navigation的作法和要注意的事項其實蠻多的,如果上述連結幫不上忙的話,可能得請您提供我原始碼我才好幫忙追問題囉~

回應

Title *
Name *
Email (將不會被顯示)
Url
Comment *

登入後使用進階評論

Please add 3 and 1 and type the answer here: