WPF快速入门系列(6)——WPF资源和样式
WPF快速入門系列(6)——WPF資源和樣式
一、引言
? WPF資源系統(tǒng)可以用來保存一些公有對象和樣式,從而實(shí)現(xiàn)重用這些對象和樣式的作用。而WPF樣式是重用元素的格式的重要手段,可以理解樣式就如CSS一樣,盡管我們可以在每個控件中定義格式,但是如果多個控件都應(yīng)用了多個格式的時候,我們就可以把這些格式封裝成格式,然后在資源中定義這個格式,之前如果用到這個格式就可以直接使用這個樣式,從而達(dá)到重用格式的手段。從中可以發(fā)現(xiàn),WPF資源和WPF樣式是相關(guān)的,我們經(jīng)常把樣式定義在資源中。
二、WPF資源詳解
2.1 資源基礎(chǔ)介紹
盡管可以在代碼中創(chuàng)建和操作資源,但是通常都是以XAML標(biāo)簽的形式定義資源的。下面具體看看如何去定義一個資源,具體的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><!--定義一個字符串資源--><sys:String x:Key="nameStr">LearningHard博客:http://www.cnblogs.com/zhili/</sys:String></Window.Resources><StackPanel><!--通過資源key來對資源進(jìn)行使用--><TextBlock Text="{StaticResource nameStr}" Margin="10"/></StackPanel> </Window>每一個元素都有一個Resources屬性,該屬性存儲了一個資源字典集合。關(guān)于資源字典將會在下面部分介紹。盡管每個元素都提供了Resources屬性,但通常在窗口級別上定義資源,就如上面XAML代碼所示的那樣。因為每個元素都可以訪問它自己的資源集合中的資源,也可以訪問所有父元素的資源集合中的資源。
2.2 靜態(tài)資源和動態(tài)資源區(qū)別
? 為了使用XAML標(biāo)記中的資源,需要一種引用資源的方法,可以通過兩個標(biāo)記來進(jìn)行引用資源:一個用于靜態(tài)資源,另一個用于動態(tài)資源。在上面的XAML中,我們引用的方式就是靜態(tài)資源的引用方式,因為我們指定了StaticResource。那靜態(tài)資源和動態(tài)資源有什么區(qū)別呢?
對于靜態(tài)資源在第一次創(chuàng)建窗口時,一次性地設(shè)置完畢;而對于動態(tài)資源,如果發(fā)生了改變,則會重新應(yīng)用資源。下面通過一個示例來演示下他們之間的區(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>對應(yīng)改變資源按鈕的后臺代碼如下所示:
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按鈕之后,只改變了動態(tài)引用資源按鈕的背景色,而靜態(tài)引用按鈕的背景卻沒有發(fā)生改變,具體效果圖如下所示:
2.3 資源字典
在前面中講到,每個Resources屬性存儲著一個資源字典集合。如果希望在多個項目之間共享資源的話,就可以創(chuàng)建一個資源字典。資源字段是一個簡單的XAML文檔,該文檔就是用于存儲資源的,可以通過右鍵項目->添加資源字典的方式來添加一個資源字典文件。下面具體看下如何去創(chuàng)建一個資源字典。具體的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)用程序資源集合中,因為資源字典的目的就是在于多個窗體中共享,具體的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>那怎樣使用資源字典中定義的資源呢?其使用方式和引用資源的方式是一樣的,一樣是通過資源的Key屬性來進(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><!--定義一個字符串資源--><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}"/><!--通過資源key來對資源進(jìn)行使用--><TextBlock Text="{StaticResource nameStr}" Margin="10"/></StackPanel> </Window>此時的運(yùn)行效果如下圖所示:
前面只是介紹在當(dāng)前應(yīng)用程序下共享資源可以把資源字典合并到應(yīng)用程序資源集合中,如果想在多個應(yīng)用程序共享資源怎么辦呢?最簡單的方法就是在每個應(yīng)用程序中拷貝一份資源字典的XAML文件,但是這樣不能對版本進(jìn)行控制,顯然這不是一個好的辦法。更好的辦法是將資源字典編譯到一個單獨(dú)的類庫程序集中,應(yīng)用程序可以通過引用程序集的方式來共享資源。這樣就達(dá)到了在多個應(yīng)用程序中共享資源的目的。
使用這種方式面臨著另一個問題,即如何獲得所需要的資源并在應(yīng)用程序中使用資源。對此,可以采用兩種方法。第一種辦法是通過代碼創(chuàng)建一個ResourceDictionary對象,再通過指定其Source屬性來定位程序中資源字典文件,一旦創(chuàng)建了ResourceDictionary對象,就可以通過key來檢索對應(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)加載一個新的資源字典時,窗口中所有的DynamicResource引用都會自動引用新的資源,這樣的方式可以用來構(gòu)建動態(tài)的皮膚功能。
另外一種辦法可以使用ComponentResourceKey標(biāo)記,使用ComponentResourceKey為資源創(chuàng)建鍵名。具體使用例子請參看博文:Defining and Using Shared Resources in a Custom Control Library。
三、WPF樣式詳解
在前面介紹了WPF資源,使用資源可以在一個地方定義對象而在整個應(yīng)用程序中重用它們,除了在資源中可以定義各種對象外,還可以定義樣式,從而達(dá)到樣式的重用。
樣式可以理解為元素的屬性集合。與Web中的CSS類似。WPF可以指定具體的元素類型為目標(biāo),并且WPF樣式還支持觸發(fā)器,即當(dāng)一個屬性發(fā)生變化的時,觸發(fā)器中的樣式才會被應(yīng)用。
3.1 WPF樣式使用
之前WPF資源其實(shí)完全可以完成WPF樣式的功能,只是WPF樣式對資源中定義的對象進(jìn)行了封裝,使其存在于樣式中,利于管理和應(yīng)用,我們可以把一些公共的屬性定義放在樣式中進(jìn)行定義,然后需要引用這些屬性的控件只需要引用具體的樣式即可,而不需要對這多個屬性進(jìn)行分別設(shè)置。下面XAML代碼就是一個樣式的使用示例:
<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)記,如果沒有顯示指定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)樣式中沒有定義key標(biāo)記時,則對應(yīng)的樣式會指定應(yīng)用到目標(biāo)對象上,上面XAML代碼就是這種情況,如果顯式為樣式定義了key標(biāo)記的話,則必須顯式指定樣式Key的方式,對應(yīng)的樣式才會被應(yīng)用到目標(biāo)對象上,下面具體看看這種情況。此時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將不會應(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>此時運(yùn)行效果如下圖所示:
3.2 樣式觸發(fā)器
WPF樣式還支持觸發(fā)器,在樣式中定義的觸發(fā)器,只有在該屬性或事件發(fā)生時才會被觸發(fā),下面具體看看簡單的樣式觸發(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)時觸發(fā)--><Trigger Property="Control.IsFocused" Value="True"><Setter Property="Control.Foreground" Value="Red" /></Trigger><!--鼠標(biāo)移過時觸發(fā)--><Trigger Property="Control.IsMouseOver" Value="True"><Setter Property="Control.Foreground" Value="Yellow" /><Setter Property="Control.FontWeight" Value="Bold" /></Trigger><!--按鈕按下時觸發(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>此時的運(yùn)行效果如下圖所示:
上面定義的觸發(fā)器都是在某個屬性發(fā)生變化時觸發(fā)的,也可以定義當(dāng)某個事件激活時的觸發(fā)器,我們也把這樣的觸發(fā)器稱為事件觸發(fā)器,下面示例定義的事件觸發(fā)器是等待MouseEnter事件,一旦觸發(fā)MouseEnter事件,則動態(tài)改變按鈕的FontSize屬性來形成動畫效果,具體的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ā)時只需的操作--><EventTrigger.Actions><!--把動畫放在動畫面板中--><BeginStoryboard><!--在0.2秒的時間內(nèi)將字體放大到22單位--><Storyboard><DoubleAnimationDuration="0:0:0.2"Storyboard.TargetProperty="FontSize"To="22" /></Storyboard></BeginStoryboard></EventTrigger.Actions></EventTrigger><!--鼠標(biāo)移開觸發(fā)的事件--><EventTrigger RoutedEvent="Mouse.MouseLeave"><EventTrigger.Actions><BeginStoryboard><!--在1秒的時間內(nèi)將字體尺寸縮小到原來的大小--><!--如果目標(biāo)字體尺寸沒有明確指定,則WPF將默認(rèn)使用第一次動畫之前按鈕的字體尺寸--><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>此時的運(yùn)行效果如下圖所示:
四、小結(jié)
到這里,WPF資源和樣式的內(nèi)容就介紹結(jié)束。總結(jié)為,WPF樣式類似CSS,可以將多個屬性定義在一個樣式中,而樣式又存放在資源中,資源成了樣式和對象的容器。另外WPF樣式還支持觸發(fā)器功能,本文中演示了屬性觸發(fā)器和事件觸發(fā)器的使用。在接下來一篇博文中將介紹WPF模板。
本文所有源碼:ResourceAndStyle.zip
轉(zhuǎn)載于:https://www.cnblogs.com/Jeely/p/11076182.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的WPF快速入门系列(6)——WPF资源和样式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win10怎么解决ime禁用 win10
- 下一篇: Quartz.Net实现作业定时调度详解