本期提要:
因?yàn)樾枰诖a中修改TextBox的Style屬性,但是我卻把本來適用于TextBlock的Style賦值給了TextBox,這樣導(dǎo)致了一個(gè)異常的彈出。開始以為是在ResourceDictionary中查找的方法不對(duì),所以對(duì)Resource Dictionary進(jìn)行了了解。就是本文的內(nèi)容了。本文主要參考MSDN的教程,并佐以實(shí)例和自己的理解,希望對(duì)大家有所幫助。本章內(nèi)容沒有圖例,所以我盡量把排版弄好一些。
Resource Dictionary簡(jiǎn)介
一言以蔽之,Resource Dictionary是放置資源的地方,以方便在其他地方進(jìn)行引用。既然是字典,那么就應(yīng)該是以鍵值對(duì)的形式存在。事實(shí)確實(shí)是如此,Resource Dictionary中的資源都有一個(gè)x:Key,其他的都是它的值。如果試圖給Resource Dictionary添加一個(gè)沒有Key的子元素,會(huì)拋出一個(gè)解析異?;蛘遰un-time異常。有兩種例外的元素不需要Key,我們會(huì)在后面介紹。
Resource Dictionary的常用的場(chǎng)景是在XAML中使用,在XAML中定義一個(gè)資源,在其他地方對(duì)其進(jìn)行StaticResouce引用。在代碼中使用也是可以的,這樣可以允許我們?cè)谶\(yùn)行時(shí)對(duì)Resource Dictionary根據(jù)我們的設(shè)想進(jìn)行相應(yīng)的調(diào)整。
為了對(duì)Resource Dictionary有個(gè)直觀的理解,我們摘取了App.XAML文件中的代碼進(jìn)行講解。
1 <Application.Resources>
2 <ResourceDictionary>
3 <ResourceDictionary.MergedDictionaries>
4
5 <!--
6 Styles that define common aspects of the platform look and feel
7 Required by Visual Studio project and item templates
8 -->
9 <ResourceDictionary Source="Common/StandardStyles.xaml"/>
10 </ResourceDictionary.MergedDictionaries>
11
12 <!-- Application-specific resources -->
13
14 <x:String x:Key="AppName">Dino-Dino</x:String>
15 </ResourceDictionary>
16 </Application.Resources>
17 </Application>
這是一個(gè)典型的Resource,包括兩個(gè)ResourceDictionary,并且這兩個(gè)ResourceDictionary都沒有Key,也沒有其他名字。其中第2行的ResourceDictionary包含了一個(gè)Key值為”AppName“的x:String類型的子元素,這個(gè)Resource Dictionary叫做主要資源字典。第3行的意思是,我們第2行的ResourceDictionary還有一個(gè)外部的資源字典,合并在這里,這個(gè)外部資源字典的路徑在第9行給出,第9行的資源字典叫做合并資源字典。
如何使用這個(gè)Resource Dictionary 中的資源呢?
1 <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Grid.Column="1" IsHitTestVisible="false" Style="{StaticResource PageHeaderTextStyle}"/>
2
這里有兩個(gè)地方都引用了資源,第一個(gè)是Text屬性,引用了Key值為”AppName“的資源,還有一個(gè)Style的屬性,引用了"Common\StandardStyle.xaml”文件中的PageHeaderTextStyle資源。
"Common/StandardStyles.xaml"文件中放了微軟為我們準(zhǔn)備的各種常用的資源,打開這個(gè)文件的話,不難發(fā)現(xiàn),這就是一個(gè)Resource Dictionary,里面有各種Style。
對(duì)Resource Dictionary有個(gè)大概的印象了,我們就可以詳細(xì)地探索一下Resource Dictionary中到底有神馬東西了。
Resource Dictionary之進(jìn)一步了解
1. 包含的內(nèi)容
--------
如果你打開"Common\StandardStyle.xaml“文件的話,你會(huì)發(fā)現(xiàn)里面有一堆的Style,不錯(cuò),Style的共享是最常見的。下面的這個(gè)就是一個(gè)例子。
1 <Style x:Key="BaselineTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}">
2 <Setter Property="LineHeight" Value="20"/>
3 <Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
4 <!-- Properly align text along its baseline -->
5 <Setter Property="RenderTransform">
6 <Setter.Value>
7 <TranslateTransform X="-1" Y="4"/>
8 </Setter.Value>
9 </Setter>
10 </Style>
------
另外還有 繼承自FramworkTemplate的模板(包括ControlTemplate、DataTemplate)
1 <DataTemplate x:Key="StandardItemTemplate">
2 <Grid HorizontalAlignment="Left">
3 <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
4 <Image Source="{Binding Image}" Stretch="UniformToFill"/>
5 </Border>
6 <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
7 <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="60" Margin="15,0,15,0"/>
8 <TextBlock Text="{Binding Subtitle}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
9 </StackPanel>
10 </Grid>
11 </DataTemplate>
------
3.Storyboard
4. Transform
5. Metrix,Matrix3D
6. Point
上面的都沒用過,所以也沒例子。
------
7. 其他與UI相關(guān)的結(jié)構(gòu),如Thickness和CornerRadius。
1 <Thickness x:Key="AppBarBottomBorderThemeThickness">0,2,0,0</Thickness>
------
8. 還有一些你自己定義的類型,轉(zhuǎn)換為本地資源的東西。自定義類型必須有一個(gè)默認(rèn)構(gòu)造函數(shù),并且在繼承關(guān)系中不能有UIElement類。這個(gè)用到過,當(dāng)時(shí)在懷疑為什么有些可以轉(zhuǎn)成本地資源,有些不可以,原來是有這些道道啊。
------
9. XAML固有數(shù)據(jù)類型
包括:x:Boolean -------區(qū)分大小寫的。不能用x:Bool代替
x:String
x:Double
x:Int32
就這四個(gè),示例如下:
1 <x:Double x:Key="AppBarThemeMinHeight">68</x:Double>
2 <x:Boolean>True</x:Boolean>
3 <x:String x:Key="AppName">Dino-Dino</x:String>
4 <x:Int32 x:Key="GamNanStyle">12</x:Int32>
------
10. 其他
1 <FontFamily x:Key="SymbolThemeFontFamily">Segoe UI Symbol</FontFamily>
2 <SolidColorBrush x:Key="AppBarBackgroundThemeBrush" Color="#E5000000" />
2. x:Key 大家還記得我們簡(jiǎn)介里面提到過的么?所有的資源都是一個(gè)鍵值對(duì),x:Key就是我們的鍵,其他的東西就是值。不設(shè)置鍵值將會(huì)引發(fā)異常,這些大家都有印象了。不過人們都很關(guān)心例外的情況,這兩種例外的情況是:Control元素 的Template屬性和具有TargetType屬性的Style元素.
第一種情況我暫時(shí)還沒有碰到,不過第二種適用于Style的可以解釋下,我們用個(gè)例子能更好地解釋一下:
1 <Style x:Key="TextButtonStyle" TargetType="Button">
2 <Setter Property="MinWidth" Value="0"/>
3 <Setter Property="MinHeight" Value="0"/>
4 <!--此處省略一些-->
5 </Style>
當(dāng)我們?cè)赬AML文件中使用Button的時(shí)候,我們可以用StaticResource來引用這種Style
1 <Button x:Name="btn1" Style={StaticResource TextButtonStyle}/>
2 <Button x:Name="btn2"/>
如果我們這么做了,那么,btn1將是TextButton類型的,它的MInWidth屬性是0, MinHeight屬性是0. 而btn2將是默認(rèn)類型,它的MinWidth和MinHeight屬性將是其他值。
如果我們的Style不使用Key的話,那么這種Style將適用于所有的TargetType。
1 <Style TargetType="Button"> <!--沒有Key-->
2 <Setter Property="MinWidth" Value="0"/>
3 <Setter Property="MinHeight" Value="0"/>
4 <!--省略-->
5 </Style>
XAML文件中:
1 <Button x:Name="btn3"/>
2 <Button x:Name="btn4"/>
btn3, btn4的MInWidth屬性都是0, MinHeight屬性都是0。 這有點(diǎn)象CSS,如果不指定類型x:Class的話,將會(huì)適用于所有Targettype.現(xiàn)在又來了個(gè)btn5,<Button x:Name="btn5" Style ={StaticResouce DinoStyleButton}/>,假設(shè)我們有DinoStyleButton的話,那么btn5將不再是MinWidth屬性為0,而是DinoStyleButton中的MinWidth中的值。
所以說,你要讓所有的Button都是一個(gè)類型的話,在Resource Dictionary中在Style中不要給它Key值就好了,如果你需要一個(gè)特殊的Style,StaticResource應(yīng)用那個(gè)Key值的Style吧,少年。
3. 直接資源和應(yīng)用資源 我們一直在談Resource Dictionary(資源字典)的問題,突然跳轉(zhuǎn)到資源上來了。不奇怪,因?yàn)槲覀兊馁Y源字典是放在這兩個(gè)資源Collection中的。
其實(shí)這兩個(gè)概念從字面上就可以很好地理解。直接資源:在該頁面上直接可以引用的資源。應(yīng)用資源:應(yīng)用級(jí)別的資源,所有的頁面都可以引用。了解么?不了解也無所謂,直接資源一般放在某一個(gè)page.XAML文件中,在文件的開始就定義好,以便本頁面可以直接引用。應(yīng)用資源:一般放在App.XAML文件中。
這是直接資源的示例:
1 <Page.Resources>
2 <CollectionViewSource
3 x:Name="groupedItemsViewSource"
4 Source="{Binding Groups}"
5 IsSourceGrouped="true"
6 ItemsPath="Items"/>
7
8 <DataTemplate x:Key="SmallDateTemplate">
9 <Grid Width="190" Height="80" Background="#421A5B22">
10 </DataTemplate>
11 </Page.Resources>
這個(gè)Page的資源中包含了兩個(gè)元素,一個(gè)是CollectionViewSource,一個(gè)是DataTemplate,你或許會(huì)說,為什么CollectionViewSource沒有Key?你這樣是錯(cuò)的。呵呵,恭喜你,在Resource Dictionary中必須要包含Key的觀念已經(jīng)深植入你的意識(shí)中,這太好了。但是,這個(gè)元素并不在一個(gè)Dictionary中。。。
你可以在MainPage.XAML中使用這些資源,但是你不能在Page2.XAML中使用。這就是直接資源的定義吧,你可以看到自己院子里面的東西,其他人卻因?yàn)楦糁鴩鷫床坏嚼锩娴臇|西。(有邏輯么?貌似沒有)
而應(yīng)用資源一般放在App.XAML中,并且放在Application.Resources中:
1 <Application.Resources>
2 <ResourceDictionary>
3 <ResourceDictionary.MergedDictionaries>
4
5 <!--
6 Styles that define common aspects of the platform look and feel
7 Required by Visual Studio project and item templates
8 -->
9 <ResourceDictionary Source="Common/StandardStyles.xaml"/>
10 </ResourceDictionary.MergedDictionaries>
11
12 <!-- Application-specific resources -->
13
14 <x:String x:Key="AppName">Dino-DailyTask</x:String>
15 </ResourceDictionary>
16 </Application.Resources>
17 </Application>
你又要說了,<ResourceDictionary.MergedDictionaries>在Dcitionary中,沒有Key,并且里面的<ResourceDictionary>也是沒有Key的。額,你是對(duì)的,他們確實(shí)沒有。微軟告訴我們,他們不需要有,并且,里面的ResourceDictionary只能有一個(gè)Source,而且就足夠了。
4. 如何引用資源字典中的資源,引用順序是如何的?
為了解決這個(gè)問題,我打亂了MSDN中教程的順序,從應(yīng)用資源開始說起,這里面的道道不多,很簡(jiǎn)單,你了解了就easy to use了。
1). 主要資源字典、合并資源字典、主題資源字典
如何引用?用StaticResource,之前我們都講過了,這里就不贅述了。那么StaticResource是怎么查找這些資源的呢?我們有直接資源,有應(yīng)用資源,應(yīng)用資源中還有主資源和合并資源,這個(gè)順序是如何?這些資源中可不可以有相同的key?
我們已經(jīng)知道了直接資源和應(yīng)用資源,也了解了應(yīng)用資源是應(yīng)用級(jí)別的資源。而這三種資源字典都是應(yīng)用資源中的概念,我再貼個(gè)代碼讓大家有個(gè)直觀的了解:
1 <Application.Resources>
2 <ResourceDictionary><!--主要資源字典 Main Dictionary-->
3 <ResourceDictionary.MergedDictionaries><!--合并資源字典 Merged Dictionary-->
4 <ResourceDictionary Source="Common/StandardStyles.xaml"/>
5 </ResourceDictionary.MergedDictionaries>
6
7 <!-- Application-specific resources -->
8
9 <x:String x:Key="AppName">Dino-DailyTask</x:String>
10 </ResourceDictionary>
11 </Application.Resources>
12 </Application>
主題資源字典不見了。。。它存在于我們的合并資源字典中,一般都是這么一個(gè)構(gòu)成的方式,下面的代碼是StandardStyle.XAML文件中的部分片段:
1 <ResourceDictionary
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
4
5 <!-- Non-brush values that vary across themes -->
6
7 <ResourceDictionary.ThemeDictionaries>
8 <ResourceDictionary x:Key="Default">
9 <x:String x:Key="BackButtonGlyph"></x:String>
10 <x:String x:Key="BackButtonSnappedGlyph"></x:String>
11 </ResourceDictionary>
12
13 <ResourceDictionary x:Key="HighContrast">
14 <x:String x:Key="BackButtonGlyph"></x:String>
15 <x:String x:Key="BackButtonSnappedGlyph"></x:String>
16 </ResourceDictionary>
17 </ResourceDictionary.ThemeDictionaries>
主要字典可以包括其他鍵控資源,也可以包含一個(gè)MergedDictionary屬性,你只能往這個(gè)屬性中添加ResourceDictionary,添加的這個(gè)ResourceDictionary就叫做合并字典。
合并字典(Merged Dictionary),它的目的就是為了使用戶可以引用外部的文件擴(kuò)充自己的資源。代碼中也可以看出,我們可以使用StandardStyle.XAML中的資源服務(wù)本程序。合并字典只能由一個(gè)Source屬性,并且不能有Key值。
主題字典是一種特殊類型的合并字典,用于保存各種資源,具體資源取決于用戶當(dāng)前在其 PC 上使用的主題。例如,“輕”主題可能使用白色畫筆,而默認(rèn)主題可能使用黑色畫筆。畫筆會(huì)更改,但使用畫筆作為資源的控件創(chuàng)作過程可能是相同的,只需引用一個(gè)主題資源。
此處的每個(gè)
ResourceDictionary 元素必須有一個(gè)
x:Key 值。該值是一個(gè)命名相關(guān)主題的字符串—例如,"Default" 或 "HighContrast“
同樣與合并字典一樣,多次定義同一個(gè)鍵是合法的,只要在每個(gè)主題字典單元中是唯一的。事實(shí)上,這是一種特意的設(shè)計(jì):每個(gè)主題字典應(yīng)該有一組相同的鍵。否則,任何缺少某個(gè)鍵的主題都可能在加載該主題時(shí)導(dǎo)致問題。不同于合并字典,每個(gè)主題的定義順序無關(guān)緊要。對(duì)于主題字典,要用于資源查找的活動(dòng)字典始終在運(yùn)行時(shí)確定。一般而言,查找邏輯基于活動(dòng)主題到一個(gè)特定主題字典的
x:Key 的映射。
了解了么?
2). 資源的查找順序:
知道了這些字典了之后,我們有個(gè)級(jí)別的概念了,就好理解資源的查找順序了,我看還是上個(gè)圖吧,比較好理解一些

用文字描述就是:先在自己的Resource里面查找,如果沒有,向父類控件的Resource中查找,如果沒有,向文件的根級(jí)別方向查找,一般就會(huì)到Page.Resource中去了,如果這里面依然沒有,就會(huì)向Application.Resource中查找。如果到達(dá)了合并字典了,我們看到箭頭是先到了Dictionary2, 而不是首先添加的Dictionary1,至于為什么,微軟是規(guī)則制定者, 我不太清楚。
3). 使用相同的Key 前面已經(jīng)說了,在一個(gè)Dictionary中不能使用相同的Key,但是如果不在同一級(jí)別,那么這個(gè)規(guī)則是可以被打破的。什么叫不是一個(gè)級(jí)別?
直接資源和應(yīng)用資源不在同一級(jí)別。
主要字典和合并字典和主題字典也不在同一級(jí)別。
不同的合并字典也不在同一級(jí)別。
不同的主題字典也不在同一級(jí)別。
1
2 <Application.Resources>
3 <ResourceDictionary>// 主要資源字典
4 <SolidColorBrush Color="#d0157820" x:Key="muddyBrush"/>//主要資源中可以有其他鍵控資源
5 <ResourceDictionary.MergedDictionaries>// 合并資源字典
6 <ResourceDictionary Source="rd1.xaml" />//ResourceDictionary中不能有其他東西,只能由Source
7 <ResourceDictionary Source="rd2.xaml" />
8 </ResourceDictionary.MergedDictionaries>
9 </ResourceDictionary>
10 </Application.Resources>
4). 資源回退機(jī)制
我們可以利用合并資源字典的查找順序和使用相同鍵值這一特性來創(chuàng)建資源回退值的優(yōu)先級(jí)順序。比如說:rd1.xaml中有一個(gè)
1 <Style x:Key="DinoDinoStyleButton" TargetType="Button"><Setter Property="BackgroundColor" Value="#ffffffff"/> </Style>
在我的MainPage.Xaml文件中我這么引用:
1 <Button x:Name="DinoButton" Style={StaticResource DinoDinoStyleButton}/>
如果我有其他要求的話,并且我不希望修改MainPage.Xaml文件,那么我可以根據(jù)合并字典的查找順序在rd2.xaml中創(chuàng)建一個(gè)鍵值相同的Style:
1 <Style x:Key="DinoDinoStyleButton" TargetType="Button"><Setter Property="BackgroundColor" Value="#11111111"/> </Style>
這樣就改變了,這就是我理解的回退值機(jī)制。
為了保證回退機(jī)制可以使用,在主要字典中必須不能包含相同的鍵值。你懂的,如果那樣的話,就會(huì)優(yōu)先找懂啊主要字典中的鍵,永遠(yuǎn)也不會(huì)找到合并字典中去。
這里有個(gè)文件可以讓大家了解相關(guān)的主題字典:使用文本編輯器打開 \(Program Files)\windows kits\8.0\Include\winrt\xaml\design 中的 XAML 文件,可以看到其主題資源的定義。
5). 雜項(xiàng)
1. 向前引用:一個(gè)資源必須定義了之后才能被引用。所以我們的資源一般放在接近開頭的位置進(jìn)行定義。
2. UserControl比較特殊,UserControl 必須能夠支持在自己的定義范圍查找序列中查找該資源—,也就是說它不能訪問應(yīng)用資源。
6). 在代碼中使用資源字典
使用Lookup方法(C++),下面是如何在應(yīng)用資源里面查找相應(yīng)的代碼:
1 if(App::Current->Resources->HasKey(L"CaptionTextStyle"))
2 {
3 auto style = safe_cast<Windows::UI::Xaml::Style^>(App::Current->Resources->Lookup("CaptionTextStyle"));
4 //auto style = safe_cast<Windows::UI::Xaml::Style^>(App::Application::Current->Resources->Lookup(L"TitleTextStyle"));
5 if(style != nullptr)
6 textblock->Style = style;
7
8 }
這里又回到開頭說的問題了,因?yàn)槲野裈argetType為TextBlock的Style賦值給了TextBox,所以造成了異常,所以在代碼中進(jìn)行操作的時(shí)候,一定要了解你的右值和左值是否對(duì)應(yīng)。
在論壇里面問到了原因,但是還是把相關(guān)的Dictionary知識(shí)了解了一下,以前只知道隨便用,現(xiàn)在大概了解它的機(jī)制了。把MSDN上的內(nèi)容看懂了,又用自己的話描述一番,感覺還是挺清楚的。雖然東西有點(diǎn)多,但是還是很有幫助的。
下一章的東西還在待定。。。
posted on 2012-10-24 16:02
Dino-Tech 閱讀(3204)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
Windows 8