WPF快速入门系列(6)——WPF资源和样式
WPF快速入門系列(6)——WPF資源和樣式
一、引言
? WPF資源系統(tǒng)可以用來(lái)保存一些公有對(duì)象和樣式,從而實(shí)現(xiàn)重用這些對(duì)象和樣式的作用。而WPF樣式是重用元素的格式的重要手段,可以理解樣式就如CSS一樣,盡管我們可以在每個(gè)控件中定義格式,但是如果多個(gè)控件都應(yīng)用了多個(gè)格式的時(shí)候,我們就可以把這些格式封裝成格式,然后在資源中定義這個(gè)格式,之前如果用到這個(gè)格式就可以直接使用這個(gè)樣式,從而達(dá)到重用格式的手段。從中可以發(fā)現(xiàn),WPF資源和WPF樣式是相關(guān)的,我們經(jīng)常把樣式定義在資源中。
二、WPF資源詳解
2.1 資源基礎(chǔ)介紹
盡管可以在代碼中創(chuàng)建和操作資源,但是通常都是以XAML標(biāo)簽的形式定義資源的。下面具體看看如何去定義一個(gè)資源,具體的XAML代碼如下所示:
<Window x:Class="ResourceDemo.ResourceUse"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="REsource" Height="100" Width="350"xmlns:sys="clr-namespace:System;assembly=mscorlib"> <Window.Resources><!--定義一個(gè)字符串資源--><sys:String x:Key="nameStr">LearningHard博客:http://www.cnblogs.com/zhili/</sys:String></Window.Resources><StackPanel><!--通過(guò)資源key來(lái)對(duì)資源進(jìn)行使用--><TextBlock Text="{StaticResource nameStr}" Margin="10"/></StackPanel> </Window>每一個(gè)元素都有一個(gè)Resources屬性,該屬性存儲(chǔ)了一個(gè)資源字典集合。關(guān)于資源字典將會(huì)在下面部分介紹。盡管每個(gè)元素都提供了Resources屬性,但通常在窗口級(jí)別上定義資源,就如上面XAML代碼所示的那樣。因?yàn)槊總€(gè)元素都可以訪問(wèn)它自己的資源集合中的資源,也可以訪問(wèn)所有父元素的資源集合中的資源。
2.2 靜態(tài)資源和動(dòng)態(tài)資源區(qū)別
? 為了使用XAML標(biāo)記中的資源,需要一種引用資源的方法,可以通過(guò)兩個(gè)標(biāo)記來(lái)進(jìn)行引用資源:一個(gè)用于靜態(tài)資源,另一個(gè)用于動(dòng)態(tài)資源。在上面的XAML中,我們引用的方式就是靜態(tài)資源的引用方式,因?yàn)槲覀冎付?strong>StaticResource。那靜態(tài)資源和動(dòng)態(tài)資源有什么區(qū)別呢?
對(duì)于靜態(tài)資源在第一次創(chuàng)建窗口時(shí),一次性地設(shè)置完畢;而對(duì)于動(dòng)態(tài)資源,如果發(fā)生了改變,則會(huì)重新應(yīng)用資源。下面通過(guò)一個(gè)示例來(lái)演示下他們之間的區(qū)別。具體的XAML代碼如下所示:
<Window x:Class="ResourceDemo.DynamicResource"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="DynamicResource" Height="300" Width="300"><Window.Resources><SolidColorBrush x:Key="RedBrush" Color="Red"></SolidColorBrush></Window.Resources><StackPanel Margin="5"><Button Background="{StaticResource RedBrush}" Margin="5" FontSize="14" Content="Use a Static Resource"/><Button Background="{DynamicResource RedBrush}" Margin="5" FontSize="14" Content="Use a Dynamic Resource"/><Button Margin="5" FontSize="14" Content="Change the RedBrush to Yellow" Click="ChangeBrushToYellow_Click"/></StackPanel> </Window>對(duì)應(yīng)改變資源按鈕的后臺(tái)代碼如下所示:
private void ChangeBrushToYellow_Click(object sender, RoutedEventArgs e){// 改變資源this.Resources["RedBrush"] = new SolidColorBrush(Colors.Yellow);}運(yùn)行上面程序,你將發(fā)現(xiàn),當(dāng)點(diǎn)擊Change按鈕之后,只改變了動(dòng)態(tài)引用資源按鈕的背景色,而靜態(tài)引用按鈕的背景卻沒(méi)有發(fā)生改變,具體效果圖如下所示:
2.3 資源字典
在前面中講到,每個(gè)Resources屬性存儲(chǔ)著一個(gè)資源字典集合。如果希望在多個(gè)項(xiàng)目之間共享資源的話,就可以創(chuàng)建一個(gè)資源字典。資源字段是一個(gè)簡(jiǎn)單的XAML文檔,該文檔就是用于存儲(chǔ)資源的,可以通過(guò)右鍵項(xiàng)目->添加資源字典的方式來(lái)添加一個(gè)資源字典文件。下面具體看下如何去創(chuàng)建一個(gè)資源字典。具體的XAML代碼如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><SolidColorBrush x:Key="blueBrush" Color="Blue"/><FontWeight x:Key="fontWeight">Bold</FontWeight> </ResourceDictionary>為了使用資源字典,需要將其合并到應(yīng)用程序中資源集合位置,當(dāng)然你也可以合并到窗口資源集合中,但是通常是合并到應(yīng)用程序資源集合中,因?yàn)橘Y源字典的目的就是在于多個(gè)窗體中共享,具體的XAML代碼如下所示:
<Application x:Class="ResourceDemo.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"StartupUri="DynamicResource.xaml"><Application.Resources><!--合并資源字典到Application.Resources中--><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Generic.xaml"/></ResourceDictionary.MergedDictionaries></ResourceDictionary></Application.Resources> </Application>那怎樣使用資源字典中定義的資源呢?其使用方式和引用資源的方式是一樣的,一樣是通過(guò)資源的Key屬性來(lái)進(jìn)行引用的,具體使用代碼如下所示:
<Window x:Class="ResourceDemo.ResourceUse"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="REsource" Height="100" Width="350"xmlns:sys="clr-namespace:System;assembly=mscorlib"><Window.Resources><!--定義一個(gè)字符串資源--><sys:String x:Key="nameStr">LearningHard博客:http://www.cnblogs.com/zhili/</sys:String></Window.Resources><StackPanel> <!--使用資源字典中定義的資源--><Button Margin="10" Background="{StaticResource blueBrush}" Content="Blue Button" FontWeight="{StaticResource fontWeight}"/><!--通過(guò)資源key來(lái)對(duì)資源進(jìn)行使用--><TextBlock Text="{StaticResource nameStr}" Margin="10"/></StackPanel> </Window>此時(shí)的運(yùn)行效果如下圖所示:
前面只是介紹在當(dāng)前應(yīng)用程序下共享資源可以把資源字典合并到應(yīng)用程序資源集合中,如果想在多個(gè)應(yīng)用程序共享資源怎么辦呢?最簡(jiǎn)單的方法就是在每個(gè)應(yīng)用程序中拷貝一份資源字典的XAML文件,但是這樣不能對(duì)版本進(jìn)行控制,顯然這不是一個(gè)好的辦法。更好的辦法是將資源字典編譯到一個(gè)單獨(dú)的類庫(kù)程序集中,應(yīng)用程序可以通過(guò)引用程序集的方式來(lái)共享資源。這樣就達(dá)到了在多個(gè)應(yīng)用程序中共享資源的目的。
使用這種方式面臨著另一個(gè)問(wèn)題,即如何獲得所需要的資源并在應(yīng)用程序中使用資源。對(duì)此,可以采用兩種方法。第一種辦法是通過(guò)代碼創(chuàng)建一個(gè)ResourceDictionary對(duì)象,再通過(guò)指定其Source屬性來(lái)定位程序中資源字典文件,一旦創(chuàng)建了ResourceDictionary對(duì)象,就可以通過(guò)key來(lái)檢索對(duì)應(yīng)的資源,具體的實(shí)現(xiàn)代碼如下:
ResourceDictionary resourceDic = new ResourceDictionary();// ReusableDictionary.xaml是資源字典文件resourceDic.Source = new Uri("ResourceLibrary;component/ReusableDictionary.xaml", UriKind.Relative);SolidColorBrush blueBrush =(SolidColorBrush)resourceDic["BlueBrush"];這種方式不需要手動(dòng)指定資源,當(dāng)加載一個(gè)新的資源字典時(shí),窗口中所有的DynamicResource引用都會(huì)自動(dòng)引用新的資源,這樣的方式可以用來(lái)構(gòu)建動(dòng)態(tài)的皮膚功能。
另外一種辦法可以使用ComponentResourceKey標(biāo)記,使用ComponentResourceKey為資源創(chuàng)建鍵名。具體使用例子請(qǐng)參看博文:Defining and Using Shared Resources in a Custom Control Library。
三、WPF樣式詳解
在前面介紹了WPF資源,使用資源可以在一個(gè)地方定義對(duì)象而在整個(gè)應(yīng)用程序中重用它們,除了在資源中可以定義各種對(duì)象外,還可以定義樣式,從而達(dá)到樣式的重用。
樣式可以理解為元素的屬性集合。與Web中的CSS類似。WPF可以指定具體的元素類型為目標(biāo),并且WPF樣式還支持觸發(fā)器,即當(dāng)一個(gè)屬性發(fā)生變化的時(shí),觸發(fā)器中的樣式才會(huì)被應(yīng)用。
3.1 WPF樣式使用
之前WPF資源其實(shí)完全可以完成WPF樣式的功能,只是WPF樣式對(duì)資源中定義的對(duì)象進(jìn)行了封裝,使其存在于樣式中,利于管理和應(yīng)用,我們可以把一些公共的屬性定義放在樣式中進(jìn)行定義,然后需要引用這些屬性的控件只需要引用具體的樣式即可,而不需要對(duì)這多個(gè)屬性進(jìn)行分別設(shè)置。下面XAML代碼就是一個(gè)樣式的使用示例:
<Window x:Class="StyleDemo.StyleDefineAndUse"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="300" Width="400"><Window.Resources><!--定義樣式--><Style TargetType="Button"><Setter Property="FontFamily" Value="Times New Roman" /><Setter Property="FontSize" Value="18" /><Setter Property="FontWeight" Value="Bold" /></Style></Window.Resources><StackPanel Margin="5"><!--由于前面定義的樣式?jīng)]有定義key標(biāo)記,如果沒(méi)有顯示指定Style為null,這按鈕將指定引用事先定義的樣式--><Button Padding="5" Margin="5">Customized Button</Button><TextBlock Margin="5">Normal Content.</TextBlock><!--使其不引用事先定義的樣式--><Button Padding="5" Margin="5" Style="{x:Null}">A Normal Button</Button></StackPanel> </Window>具體的運(yùn)行效果如下圖所示:
當(dāng)樣式中沒(méi)有定義key標(biāo)記時(shí),則對(duì)應(yīng)的樣式會(huì)指定應(yīng)用到目標(biāo)對(duì)象上,上面XAML代碼就是這種情況,如果顯式為樣式定義了key標(biāo)記的話,則必須顯式指定樣式Key的方式,對(duì)應(yīng)的樣式才會(huì)被應(yīng)用到目標(biāo)對(duì)象上,下面具體看看這種情況。此時(shí)XAML代碼如下所示:
<Window x:Class="StyleDemo.ReuseFontWithStyles"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="ReuseFontWithStyles" Height="300" Width="300"><Window.Resources><!--帶有key標(biāo)簽的樣式--><Style TargetType="Button" x:Key="BigButtonStyle"><Setter Property="FontFamily" Value="Times New Roman" /><Setter Property="FontSize" Value="18" /><Setter Property="FontWeight" Value="Bold" /></Style></Window.Resources><StackPanel Margin="5"><!--如果不顯式指定樣式key將不會(huì)應(yīng)用樣式--><Button Padding="5" Margin="5">Normal Button</Button><Button Padding="5" Margin="5" Style="{StaticResource BigButtonStyle}">Big Button</Button><TextBlock Margin="5">Normal Content.</TextBlock><!--使其不引用事先定義的樣式--><Button Padding="5" Margin="5" Style="{x:Null}">A Normal Button</Button></StackPanel> </Window>此時(shí)運(yùn)行效果如下圖所示:
3.2 樣式觸發(fā)器
WPF樣式還支持觸發(fā)器,在樣式中定義的觸發(fā)器,只有在該屬性或事件發(fā)生時(shí)才會(huì)被觸發(fā),下面具體看看簡(jiǎn)單的樣式觸發(fā)器是如何定義和使用的,具體的XAML代碼如下所示:
<Window x:Class="StyleDemo.SimpleTriggers"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="SimpleTriggers" Height="300" Width="300"><Window.Resources><Style x:Key="BigFontButton"><Style.Setters><Setter Property="Control.FontFamily" Value="Times New Roman" /><Setter Property="Control.FontSize" Value="18" /></Style.Setters><!--樣式觸發(fā)器--><Style.Triggers><!--獲得焦點(diǎn)時(shí)觸發(fā)--><Trigger Property="Control.IsFocused" Value="True"><Setter Property="Control.Foreground" Value="Red" /></Trigger><!--鼠標(biāo)移過(guò)時(shí)觸發(fā)--><Trigger Property="Control.IsMouseOver" Value="True"><Setter Property="Control.Foreground" Value="Yellow" /><Setter Property="Control.FontWeight" Value="Bold" /></Trigger><!--按鈕按下時(shí)觸發(fā)--><Trigger Property="Button.IsPressed" Value="True"><Setter Property="Control.Foreground" Value="Blue" /></Trigger></Style.Triggers></Style></Window.Resources><StackPanel Margin="5"><Button Padding="5" Margin="5"Style="{StaticResource BigFontButton}" >A Big Button</Button><TextBlock Margin="5">Normal Content.</TextBlock><Button Padding="5" Margin="5">A Normal Button</Button></StackPanel> </Window>此時(shí)的運(yùn)行效果如下圖所示:
上面定義的觸發(fā)器都是在某個(gè)屬性發(fā)生變化時(shí)觸發(fā)的,也可以定義當(dāng)某個(gè)事件激活時(shí)的觸發(fā)器,我們也把這樣的觸發(fā)器稱為事件觸發(fā)器,下面示例定義的事件觸發(fā)器是等待MouseEnter事件,一旦觸發(fā)MouseEnter事件,則動(dòng)態(tài)改變按鈕的FontSize屬性來(lái)形成動(dòng)畫(huà)效果,具體的XAML代碼如下所示:
<Window x:Class="StyleDemo.EventTrigger"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="EventTrigger" Height="300" Width="300"><Window.Resources><Style x:Key="BigFontButton"><Style.Setters><Setter Property="Control.FontFamily" Value="Times New Roman" /><Setter Property="Control.FontSize" Value="18" /><Setter Property="Control.FontWeight" Value="Bold" /></Style.Setters><Style.Triggers><!--定義事件觸發(fā)器--><EventTrigger RoutedEvent="Mouse.MouseEnter"><!--事件觸發(fā)時(shí)只需的操作--><EventTrigger.Actions><!--把動(dòng)畫(huà)放在動(dòng)畫(huà)面板中--><BeginStoryboard><!--在0.2秒的時(shí)間內(nèi)將字體放大到22單位--><Storyboard><DoubleAnimationDuration="0:0:0.2"Storyboard.TargetProperty="FontSize"To="22" /></Storyboard></BeginStoryboard></EventTrigger.Actions></EventTrigger><!--鼠標(biāo)移開(kāi)觸發(fā)的事件--><EventTrigger RoutedEvent="Mouse.MouseLeave"><EventTrigger.Actions><BeginStoryboard><!--在1秒的時(shí)間內(nèi)將字體尺寸縮小到原來(lái)的大小--><!--如果目標(biāo)字體尺寸沒(méi)有明確指定,則WPF將默認(rèn)使用第一次動(dòng)畫(huà)之前按鈕的字體尺寸--><Storyboard><DoubleAnimationDuration="0:0:1"Storyboard.TargetProperty="FontSize" /></Storyboard></BeginStoryboard></EventTrigger.Actions></EventTrigger></Style.Triggers></Style> </Window.Resources><StackPanel Margin="5"><Button Padding="5" Margin="5"Style="{StaticResource BigFontButton}" >A Big Button</Button><TextBlock Margin="5">Normal Content.</TextBlock><Button Padding="5" Margin="5">A Normal Button</Button></StackPanel> </Window>此時(shí)的運(yùn)行效果如下圖所示:
四、小結(jié)
到這里,WPF資源和樣式的內(nèi)容就介紹結(jié)束。總結(jié)為,WPF樣式類似CSS,可以將多個(gè)屬性定義在一個(gè)樣式中,而樣式又存放在資源中,資源成了樣式和對(duì)象的容器。另外WPF樣式還支持觸發(fā)器功能,本文中演示了屬性觸發(fā)器和事件觸發(fā)器的使用。在接下來(lái)一篇博文中將介紹WPF模板。
本文所有源碼:ResourceAndStyle.zip
轉(zhuǎn)載于:https://www.cnblogs.com/Jeely/p/11076182.html
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的WPF快速入门系列(6)——WPF资源和样式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: win10怎么解决ime禁用 win10
- 下一篇: Error querying datab
