本文內(nèi)容
- 使用 XAML 中的資源
- 靜態(tài)和動(dòng)態(tài)資源
- 靜態(tài)資源
- 動(dòng)態(tài)資源
- 樣式、DataTemplate 和隱式鍵
資源是可以在應(yīng)用中的不同位置重復(fù)使用的對(duì)象。 資源的示例包括畫筆和樣式。 本概述介紹如何使用 Extensible Application Markup Language (XAML) 中的資源。 你還可以使用代碼創(chuàng)建和訪問資源。
?備注
本文所述的 XAML 資源與應(yīng)用資源不同,后者通常指添加到應(yīng)用中的文件,例如內(nèi)容、數(shù)據(jù)或嵌入式文件。
1、使用 XAML 中的資源
下面的示例將?SolidColorBrush?定義為頁面根元素上的資源。 該示例隨后引用資源,并使用它來設(shè)置多個(gè)子元素的屬性,其中包括?Ellipse、TextBlock?和?Button。
<Page Name="root"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Page.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="Blue"/>
</Style>
<Style TargetType="TextBlock" x:Key="TitleText">
<Setter Property="Background" Value="Blue"/>
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="#4E87D4"/>
<Setter Property="FontFamily" Value="Trebuchet MS"/>
<Setter Property="Margin" Value="0,40,10,10"/>
</Style>
<Style TargetType="TextBlock" x:Key="Label">
<Setter Property="DockPanel.Dock" Value="Right"/>
<Setter Property="FontSize" Value="8"/>
<Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,3,10,0"/>
</Style>
</Page.Resources>
<StackPanel>
<Border Style="{StaticResource PageBackground}">
<DockPanel>
<TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
<TextBlock Style="{StaticResource Label}">Label</TextBlock>
<TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
<Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
<Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="40" />
</DockPanel>
</Border>
</StackPanel>
</Page>
每個(gè)框架級(jí)元素(FrameworkElement?或?FrameworkContentElement)都具有?Resources?屬性,該屬性是包含已定義資源的?ResourceDictionary?類型。 你可以在任何元素上定義資源,例如?Button。 但是,最常在根元素上定義資源,本示例中的根元素為?Page。
資源字典中的每個(gè)資源都必須具有唯一鍵。 在標(biāo)記中定義資源時(shí),可通過?x:Key 指令來分配唯一鍵。 通常情況下,這個(gè)鍵是一個(gè)字符串;但是,也可使用相應(yīng)的標(biāo)記擴(kuò)展將其設(shè)置為其他對(duì)象類型。 資源的非字符串鍵用于 WPF 中的某些功能區(qū),尤其是樣式、組件資源和數(shù)據(jù)樣式。
你可以使用具有資源標(biāo)記擴(kuò)展語法(指定資源的鍵名)的已定義資源。 例如,將資源用作另一個(gè)元素上的屬性的值。
<Button Background="{StaticResource MyBrush}"/>
<Ellipse Fill="{StaticResource MyBrush}"/>
在前面的示例中,如果 XAML 加載程序處理?Button?上?Background?屬性的值?{StaticResource MyBrush}
,則資源查找邏輯會(huì)首先檢查?Button?元素的資源字典。 如果?Button?沒有資源鍵?MyBrush
?的定義(在該示例中沒有;其資源集合為空),則查找邏輯接下來會(huì)檢查?Button?的父元素,即?Page。 如果在?Page?根元素上定義資源,則?Page?的邏輯樹中的所有元素都可以訪問它。 而且,你可以重復(fù)使用相同的資源來設(shè)置接受與該資源所表示類型相同的類型的所有屬性的值。 在前面的示例中,同一?MyBrush
?資源設(shè)置兩個(gè)不同的屬性:Button?的?Background?和?Rectangle?的?Fill。
2、靜態(tài)和動(dòng)態(tài)資源
資源可引用為靜態(tài)資源或動(dòng)態(tài)資源。 可通過使用?
StaticResource 標(biāo)記擴(kuò)展或?
DynamicResource 標(biāo)記擴(kuò)展創(chuàng)建引用。 標(biāo)記擴(kuò)展是 XAML 的一項(xiàng)功能,可以通過使用標(biāo)記擴(kuò)展來處理屬性字符串并將對(duì)象返回到 XAML 加載程序,從而指定對(duì)象引用。?
使用標(biāo)記擴(kuò)展時(shí),通常會(huì)以字符串的形式提供一個(gè)或多個(gè)由該特定標(biāo)記擴(kuò)展處理的參數(shù)。?
StaticResource 標(biāo)記擴(kuò)展通過在所有可用的資源字典中查找鍵值來處理鍵。 處理在加載期間進(jìn)行,即加載過程需要分配屬性值時(shí)。DynamicResource 標(biāo)記擴(kuò)展
則通過創(chuàng)建表達(dá)式來處理鍵,而且表達(dá)式會(huì)保持未計(jì)算狀態(tài),直至應(yīng)用運(yùn)行為止。當(dāng)應(yīng)用實(shí)際運(yùn)行時(shí),表達(dá)式會(huì)進(jìn)行計(jì)算并提供一個(gè)值。
在引用某個(gè)資源時(shí),下列注意事項(xiàng)可能會(huì)對(duì)于使用靜態(tài)資源引用還是使用動(dòng)態(tài)資源引用產(chǎn)生影響:
-
確定如何為應(yīng)用創(chuàng)建資源的整體設(shè)計(jì)(在每頁上、在應(yīng)用程序中、在寬松的 XAML 中或在僅包含資源的程序集中)時(shí),請(qǐng)考慮以下事項(xiàng):
-
應(yīng)用的功能。 實(shí)時(shí)更新資源是否為應(yīng)用要求的一部分?
-
該資源引用類型的相應(yīng)查找行為。
-
特定的屬性或資源類型,以及這些類型的本機(jī)行為。
3、靜態(tài)資源
在以下情況下,最適合使用靜態(tài)資源引用:
-
應(yīng)用設(shè)計(jì)將其大多數(shù)資源集中到頁面或應(yīng)用程序級(jí)資源字典中。 靜態(tài)資源引用不基于運(yùn)行時(shí)行為(例如重載頁面)重新計(jì)算。 因此,根據(jù)資源和應(yīng)用設(shè)計(jì),如果避免不必要地使用大量動(dòng)態(tài)資源引用,可能會(huì)一定程度地提高性能。
-
要設(shè)置不在?DependencyObject?或?Freezable?上的屬性的值。
-
要?jiǎng)?chuàng)建的資源字典將編譯成 DLL,并將打包為應(yīng)用的一部分或在應(yīng)用間共享。
-
要為自定義控件創(chuàng)建主題,并要定義在主題中使用的資源。 在這種情況下,通常不希望執(zhí)行動(dòng)態(tài)資源引用查找行為,而是希望執(zhí)行靜態(tài)資源引用行為,以確保查找可預(yù)測(cè)并自包含到主題中。 使用動(dòng)態(tài)資源引用時(shí),即使主題中的引用也會(huì)在運(yùn)行時(shí)前保持未計(jì)算狀態(tài)。 而且,主題可能會(huì)得到應(yīng)用,但某個(gè)本地元素仍會(huì)重新定義主題正嘗試引用的鍵,并且該本地元素在查找期間會(huì)排在主題之前。 如果發(fā)生這種情況,主題的行為將偏離預(yù)期方式。
-
要使用資源設(shè)置大量依賴屬性。 依賴屬性會(huì)通過屬性系統(tǒng)啟用有效值緩存功能;因此,如果為可在加載時(shí)進(jìn)行計(jì)算的依賴屬性提供了值,則該依賴屬性不必檢查是否存在重新計(jì)算的表達(dá)式并可返回最后一個(gè)有效值。 此項(xiàng)技術(shù)可以提高性能。
-
想為所有使用者更改基礎(chǔ)資源,或想通過使用?x:Shared 屬性為每個(gè)使用者維護(hù)單獨(dú)的可寫實(shí)例。
靜態(tài)資源查找行為
下面介紹屬性或元素引用靜態(tài)資源時(shí)自動(dòng)發(fā)生的查找過程:
-
查找進(jìn)程在用于設(shè)置屬性的元素所定義的資源字典中查找請(qǐng)求的鍵。
-
查找過程隨后會(huì)向上遍歷邏輯樹,以查找父元素及其資源字典。 此過程到達(dá)根元素后才會(huì)停止。
-
檢查應(yīng)用資源。 應(yīng)用資源就是?Application?對(duì)象為 WPF 應(yīng)用定義的資源字典中的資源。
從資源字典中進(jìn)行的靜態(tài)資源引用必須引用已在資源引用前進(jìn)行過詞法定義的資源。 靜態(tài)資源引用無法解析前向引用。 因此,請(qǐng)?jiān)O(shè)計(jì)資源字典的結(jié)構(gòu),以便在每個(gè)相應(yīng)資源字典的開頭或鄰近開頭的位置定義資源。
靜態(tài)資源查找可以擴(kuò)展到主題或系統(tǒng)資源中,但此查找受支持只是因?yàn)?XAML 加載程序推遲了請(qǐng)求。 為了讓頁面加載時(shí)的運(yùn)行時(shí)主題正確地應(yīng)用到應(yīng)用,這種延遲是必需的。 但是,不建議使用對(duì)已知僅在主題中存在或作為系統(tǒng)資源存在的鍵的靜態(tài)資源引用,因?yàn)槿绻脩魧?shí)時(shí)更改主題,不會(huì)重新計(jì)算此類引用。 請(qǐng)求主題或系統(tǒng)資源時(shí),動(dòng)態(tài)資源引用更為可靠。 例外情況是當(dāng)主題元素自身請(qǐng)求另一個(gè)資源。 出于上述原因,這些引用應(yīng)該是靜態(tài)資源引用。
因找不到靜態(tài)資源引用而引發(fā)的異常行為各不相同。 如果資源被延遲,則異常會(huì)在運(yùn)行時(shí)發(fā)生。 如果資源未延遲,則異常會(huì)在加載時(shí)發(fā)生。
4、動(dòng)態(tài)資源
在以下情況下,最適合使用動(dòng)態(tài)資源:
-
資源(包括系統(tǒng)資源或用戶可設(shè)置的資源)的值取決于直到運(yùn)行時(shí)才知道的條件。 例如,你可以創(chuàng)建 setter 值(引用由?SystemColors、SystemFonts?或?SystemParameters?公開的系統(tǒng)屬性)。 這些值是真正的動(dòng)態(tài)值,因?yàn)樗鼈冏罱K來自用戶和操作系統(tǒng)的運(yùn)行時(shí)環(huán)境。 或許還擁有可能會(huì)發(fā)生變化的應(yīng)用程序級(jí)主題,而頁面級(jí)資源訪問也必須捕獲其中的變化。
-
要為自定義控件創(chuàng)建或引用主題樣式。
-
打算在應(yīng)用生存期內(nèi)調(diào)整?ResourceDictionary?的內(nèi)容。
-
擁有存在相互依賴關(guān)系且可能需要進(jìn)行前向引用的復(fù)雜資源結(jié)構(gòu)。 靜態(tài)資源引用不支持前向引用,但動(dòng)態(tài)資源引用支持,因?yàn)橘Y源在運(yùn)行時(shí)之前不需要計(jì)算,所以前向引用是一個(gè)不相關(guān)的概念。
-
要引用從編譯或工作集的角度來看很大的資源,而且該資源在頁面加載時(shí)可能不會(huì)立即使用。 頁面加載時(shí),始終會(huì)從 XAML 加載靜態(tài)資源引用。 但是,動(dòng)態(tài)資源引用在使用前不會(huì)加載。
-
要?jiǎng)?chuàng)建的樣式的 setter 值可能來自受主題或其他用戶設(shè)置影響的其他值。
-
要將資源應(yīng)用于可能會(huì)在應(yīng)用生存期內(nèi)在邏輯樹中重定父級(jí)的元素。 父級(jí)更改后,資源查找范圍也可能會(huì)隨之更改;因此,如果希望重定父級(jí)的元素的資源基于新范圍重新進(jìn)行計(jì)算,請(qǐng)始終使用動(dòng)態(tài)資源引用。
動(dòng)態(tài)資源查找行為
如果調(diào)用?FindResource?或?SetResourceReference,則動(dòng)態(tài)資源引用的資源查找行為會(huì)與代碼中的查找行為并行執(zhí)行:
-
查找在用于設(shè)置屬性的元素所定義的資源字典中查找請(qǐng)求的鍵:
-
如果元素定義?Style?屬性,則該元素的?System.Windows.FrameworkElement.Style?將檢查其?Resources?字典。
-
如果元素定義?Template?屬性,則檢查該元素的?System.Windows.FrameworkTemplate.Resources?字典。
-
-
查找會(huì)向上遍歷邏輯樹,以查找父元素及其資源字典。 此過程到達(dá)根元素后才會(huì)停止。
-
檢查應(yīng)用資源。 應(yīng)用資源就是?Application?對(duì)象為 WPF 應(yīng)用定義的資源字典中的資源。
-
檢查主題資源字典中當(dāng)前處于活動(dòng)狀態(tài)的主題。 如果主題在運(yùn)行時(shí)發(fā)生更改,則會(huì)重新計(jì)算值。
-
檢查系統(tǒng)資源。
異常行為(如果有)各不相同:
-
如果?FindResource?調(diào)用請(qǐng)求了某個(gè)資源但未找到該資源,則會(huì)引發(fā)異常。
-
如果?TryFindResource?調(diào)用請(qǐng)求了某個(gè)資源但未找到該資源,不會(huì)引發(fā)任何異常,并且返回的值為?
null
。 如果要設(shè)置的屬性不接受?null
,則仍有可能引發(fā)更深的異常(取決于要設(shè)置的單獨(dú)屬性)。 -
如果 XAML 中的動(dòng)態(tài)資源引用請(qǐng)求了某個(gè)資源但未找到該資源,則行為取決于常規(guī)屬性系統(tǒng)。 常規(guī)行為即存在資源的級(jí)別上沒有發(fā)生屬性設(shè)置操作時(shí)執(zhí)行的行為。 例如,如果嘗試使用無法計(jì)算的資源來設(shè)置個(gè)別按鈕元素上的背景,則值設(shè)置操作不會(huì)產(chǎn)生任何結(jié)果,但有效值可能仍來自屬性系統(tǒng)和值優(yōu)先級(jí)中的其他參與者。 例如,背景值可能仍來自在本地定義的某個(gè)按鈕樣式,或來自主題樣式。 對(duì)于并非由主題樣式定義的屬性,資源計(jì)算失敗后的有效值可能來自屬性元數(shù)據(jù)中的默認(rèn)值。
限制
動(dòng)態(tài)資源引用存在一些重要限制。 必須至少滿足以下條件之一:
-
要設(shè)置的屬性必須是?FrameworkElement?或?FrameworkContentElement?上的屬性。 該屬性必須由?DependencyProperty?支持。
-
該引用用于?
StyleSetter
?內(nèi)的值。 -
要設(shè)置的屬性必須是?Freezable(以?FrameworkElement?或?FrameworkContentElement?屬性的值或?Setter?值的形式提供)上的屬性。
由于要設(shè)置的屬性必須是?DependencyProperty?或?Freezable?屬性,大多數(shù)屬性更改都可以傳播到 UI,這是因?yàn)閷傩愿模ǜ牡膭?dòng)態(tài)資源值)會(huì)經(jīng)由屬性系統(tǒng)確認(rèn)。 大多數(shù)控件都包含相應(yīng)的邏輯;當(dāng)?DependencyProperty?有所更改且該屬性可能會(huì)影響布局時(shí),該邏輯將強(qiáng)制使用控件的其他布局。 但是,并不保證所有使用?DynamicResource 標(biāo)記擴(kuò)展作為其值的屬性都能在 UI 中提供實(shí)時(shí)更新。 此功能可能仍會(huì)因?qū)傩?、屬性所屬的類型,甚至?yīng)用的邏輯結(jié)構(gòu)而異。
5、樣式、DataTemplate 和隱式鍵
盡管?ResourceDictionary?中的所有項(xiàng)都必須具有鍵,但這并不意味著所有資源都必須具有顯式?x:Key
。 多種對(duì)象類型在定義為資源時(shí)都支持隱式鍵,其鍵值會(huì)與另一屬性的值綁定。 這類鍵被稱為隱式鍵,而?x:Key
?屬性為顯式鍵。 任何隱式鍵都可通過指定顯式鍵來覆蓋。
關(guān)于資源,一個(gè)重要的方案就是用于定義?Style。 事實(shí)上,Style?幾乎總會(huì)作為資源字典中的條目進(jìn)行定義,因?yàn)闃邮皆诒举|(zhì)上可供重復(fù)使用。?
控件樣式可通過隱式鍵來創(chuàng)建和引用。 用于定義控件默認(rèn)外觀的主題樣式依賴于該隱式鍵。 從請(qǐng)求的角度來看,隱式鍵是控件本身的?Type。 從定義資源的角度來看,隱式鍵是樣式的?TargetType。 因此,如果要?jiǎng)?chuàng)建自定義控件的主題或要?jiǎng)?chuàng)建會(huì)與現(xiàn)有主題樣式交互的樣式,則無需為該?Style?指定?x:Key 指令。 另外,如果想要使用主題樣式,則根本無需指定任何樣式。 例如,即使?Style?資源似乎沒有鍵,以下樣式定義仍起作用:
<Style TargetType="Button">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="AliceBlue"/>
<GradientStop Offset="1.0" Color="Salmon"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="18"/>
</Style>
該樣式確實(shí)具有一個(gè)鍵:隱式鍵?typeof(System.Windows.Controls.Button)
。 在標(biāo)記中,可以直接將?TargetType?指定為類型名稱(或者,可以選擇使用?{x:Type...},以返回?Type。
通過 WPF 使用的默認(rèn)主題樣式機(jī)制,即使?Button?本身不嘗試指定其?Style?屬性或?qū)邮降奶囟ㄙY源引用,該樣式也將作為頁面上?Button?的運(yùn)行時(shí)樣式應(yīng)用。 在頁面中定義的樣式位于查找序列中的靠前位置(在主題字典樣式之前),其所用的鍵與主題字典樣式的鍵相同。 可以在頁面上的任意位置指定?<Button>Hello</Button>
,使用?Button
?的?TargetType?定義的樣式將應(yīng)用于該按鈕。 如果需要,仍可為此樣式顯式指定與?TargetType?的類型值相同的鍵,以求在標(biāo)記中清楚明示,但這是可選的。
如果?OverridesDefaultStyle?為?true
,則樣式的隱式鍵不會(huì)應(yīng)用于控件。 (另請(qǐng)注意,OverridesDefaultStyle?可能被設(shè)置為控件類的本機(jī)行為的一部分,而不是在控件的實(shí)例上顯式設(shè)置。)此外,為了支持在派生類方案中使用隱式鍵,控件必須替代?DefaultStyleKey(作為 WPF 的一部分提供的所有現(xiàn)有控件都包括此替代)。文章來源:http://www.zghlxwxcb.cn/news/detail-795863.html
DataTemplate?也有一個(gè)隱式鍵。?DataTemplate?的隱式鍵是?DataType?屬性值。?DataType?也可以作為類型的名稱來指定,而不是使用?{x:Type...}?來顯式指定。文章來源地址http://www.zghlxwxcb.cn/news/detail-795863.html
到了這里,關(guān)于【W(wǎng)PF.NET開發(fā)】WPF中的XAML資源的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!