XAML资源是可以多次使用的对象的定义。 ResourceDictionary允许在单个位置定义资源,并在整个Xamarin.Forms应用程序中重新使用。 本文介绍了如何创建和使用ResourceDictionary,以及如何合并资源字典。
概观
ResourceDictionary是由Xamarin.Forms应用程序使用的资源的存储库。 存储在ResourceDictionary中的典型资源包括样式,控件模板,数据模板,颜色和转换器。
在XAML中,资源在ResourceDictionary中定义,然后通过使用StaticResource标记扩展检索并应用于元素。 在C#中,资源在ResourceDictionary中定义,然后通过使用基于字符串的索引器检索并应用到元素。 但是,在C#中使用ResourceDictionary几乎没有什么优势,因为资源可以直接分配给可视元素的属性,而无需先从ResourceDictionary中检索它们。
创建和使用ResourceDictionary
可以在连接到页面或控件的资源集合或应用程序的资源集合的ResourceDictionary中定义资源。 选择在哪里定义ResourceDictionary会影响可以使用的地方:
-
在控制级定义的ResourceDictionary中的资源只能应用于控件及其子级。
-
在页面级定义的ResourceDictionary中的资源只能应用于页面及其子级。
-
在应用程序级定义的ResourceDictionary中的资源可以应用于整个应用程序。
以下XAML代码示例显示了在应用程序级别ResourceDictionary中定义的资源:
-
<Application ...>
-
<Application.Resources>
-
<ResourceDictionary>
-
<Color x:Key="PageBackgroundColor">Yellow</Color>
-
<Color x:Key="HeadingTextColor">Black</Color>
-
<Color x:Key="NormalTextColor">Blue</Color>
-
<Style x:Key="LabelPageHeadingStyle" TargetType="Label">
-
<Setter Property="FontAttributes" Value="Bold" />
-
<Setter Property="HorizontalOptions" Value="Center" />
-
<Setter Property="TextColor" Value="{StaticResource HeadingTextColor}" />
-
</Style>
-
</ResourceDictionary>
-
</Application.Resources>
-
</Application>
这个ResourceDictionary定义了三个Color资源和一个Style资源。 有关创建XAML App类的更多信息,请参阅App类。
每个资源都有一个使用x:Key属性指定的键,在ResourceDictionary中给它一个描述性键。 密钥用于通过StaticResource标记扩展从ResourceDictionary中检索资源,如以下XAML代码示例所示,该示例显示了在控制级别ResourceDictionary中定义的其他资源:
-
<StackLayout Margin="0,20,0,0">
-
<StackLayout.Resources>
-
<ResourceDictionary>
-
<Style x:Key="LabelNormalStyle" TargetType="Label">
-
<Setter Property="TextColor" Value="{StaticResource NormalTextColor}" />
-
</Style>
-
<Style x:Key="MediumBoldText" TargetType="Button">
-
<Setter Property="FontSize" Value="Medium" />
-
<Setter Property="FontAttributes" Value="Bold" />
-
</Style>
-
</ResourceDictionary>
-
</StackLayout.Resources>
-
<Label Text="ResourceDictionary Demo" Style="{StaticResource LabelPageHeadingStyle}" />
-
<Label Text="This app demonstrates consuming resources that have been defined in resource dictionaries."
-
Margin="10,20,10,0"
-
Style="{StaticResource LabelNormalStyle}" />
-
<Button Text="Navigate"
-
Clicked="OnNavigateButtonClicked"
-
TextColor="{StaticResource NormalTextColor}"
-
Margin="0,20,0,0"
-
HorizontalOptions="Center"
-
Style="{StaticResource MediumBoldText}" />
-
</StackLayout>
第一个Label实例检索并使用应用程序级ResourceDictionary中定义的LabelPageHeadingStyle资源,第二个Label实例检索并使用控件级ResourceDictionary中定义的LabelNormalStyle资源。 同样,Button实例检索并使用应用程序级ResourceDictionary中定义的NormalTextColor资源和控制级ResourceDictionary中定义的MediumBoldText资源。 这将导致以下屏幕截图中显示的外观:
注意:特定于单个页面的资源不应包含在应用程序级资源字典中,因为这些资源将在应用程序启动时被解析,而不是在页面需要时解析。 有关更多信息,请参阅减少应用程序资源字典大小。
重写资源
当ResourceDictionary资源共享x:Key属性值时,在视图层次结构中定义较低的资源将优先于定义较高的资源。 例如,在应用程序级别将PageBackgroundColor资源设置为蓝色将被设置为黄色的页面级PageBackgroundColor资源覆盖。 同样,页面级PageBackgroundColor资源将被控件级PageBackgroundColor资源覆盖。 以下XAML代码示例演示了这种优先级:
-
<ContentPage ... BackgroundColor="{StaticResource PageBackgroundColor}">
-
<ContentPage.Resources>
-
<ResourceDictionary>
-
<Color x:Key="PageBackgroundColor">Blue</Color>
-
<Color x:Key="NormalTextColor">Yellow</Color>
-
</ResourceDictionary>
-
</ContentPage.Resources>
-
<StackLayout Margin="0,20,0,0">
-
...
-
<Label Text="ResourceDictionary Demo" Style="{StaticResource LabelPageHeadingStyle}" />
-
<Label Text="This app demonstrates consuming resources that have been defined in resource dictionaries."
-
Margin="10,20,10,0"
-
Style="{StaticResource LabelNormalStyle}" />
-
<Button Text="Navigate"
-
Clicked="OnNavigateButtonClicked"
-
TextColor="{StaticResource NormalTextColor}"
-
Margin="0,20,0,0"
-
HorizontalOptions="Center"
-
Style="{StaticResource MediumBoldText}" />
-
</StackLayout>
-
</ContentPage>
在应用程序级别定义的原始PageBackgroundColor和NormalTextColor实例将被在页面级定义的PageBackgroundColor和NormalTextColor实例覆盖。 因此,页面背景颜色变为蓝色,页面上的文本变为黄色,如以下屏幕截图所示:
但是请注意,NavigationPage的背景栏仍为黄色,因为BarBackgroundColor属性设置为应用程序级ResourceDictionary中定义的PageBackgroundColor资源的值。
合并资源字典
合并资源字典将一个或多个ResourceDictionary实例组合到另一个中。 这可以通过将ResourceDictionary.MergedDictionaries属性设置为将被合并到应用程序,页面或控件级别ResourceDictionary中的一个或多个资源字典来实现。
ResourceDictionary类型还具有MergedWith属性,可用于将单个ResourceDictionary合并到另一个中,将ResourceDictionary指定为将MergedWith属性的值合并到当前ResourceDictionary实例中。 当通过MergedWith属性进行合并时,当前ResourceDictionary中将共享x:Key属性值与ResourceDictionary中要合并资源的任何资源将被替换。 但是,MergedWith属性将在Xamarin.Forms的未来版本中被弃用。 因此,建议使用MergedDictionaries属性来合并ResourceDictionary实例。
以下XAML代码示例显示了一个名为MyResourceDictionary的ResourceDictionary,其中包含一个资源:
-
<ResourceDictionary xmlns=""
-
xmlns:x=""
-
x:Class="ResourceDictionaryDemo.MyResourceDictionary">
-
<DataTemplate x:Key="PersonDataTemplate">
-
<ViewCell>
-
<Grid>
-
<Grid.ColumnDefinitions>
-
<ColumnDefinition Width="0.5*" />
-
<ColumnDefinition Width="0.2*" />
-
<ColumnDefinition Width="0.3*" />
-
</Grid.ColumnDefinitions>
-
<Label Text="{Binding Name}" TextColor="{StaticResource NormalTextColor}" FontAttributes="Bold" />
-
<Label Grid.Column="1" Text="{Binding Age}" TextColor="{StaticResource NormalTextColor}" />
-
<Label Grid.Column="2" Text="{Binding Location}" TextColor="{StaticResource NormalTextColor}" HorizontalTextAlignment="End" />
-
</Grid>
-
</ViewCell>
-
</DataTemplate>
-
</ResourceDictionary>
MyResourceDictionary可以合并到任何应用程序,页面或控件级别的ResourceDictionary中。 以下XAML代码示例显示使用MergedDictionaries属性将其合并到页面级ResourceDictionary中:
-
<ContentPage ...>
-
<ContentPage.Resources>
-
<ResourceDictionary>
-
<ResourceDictionary.MergedDictionaries>
-
<local:MyResourceDictionary />
-
<!-- Add more resource dictionaries here -->
-
</ResourceDictionary.MergedDictionaries>
-
</ResourceDictionary>
-
</ContentPage.Resources>
-
...
-
</ContentPage>
当合并的ResourceDictionary资源共享相同的x:Key属性值时,Xamarin.Forms使用以下资源优先级:
-
资源字典的本地资源。
-
包含在通过MergedWith属性合并的资源字典中的资源。
-
通过MergedDictionaries集合合并的资源字典中包含的资源,按MergedDictionaries属性中列出的顺序排列。
注意:如果应用程序包含多个大型资源字典,则搜索资源字典可能是一个计算密集型任务。 因此,请确保应用程序中的每个页面仅使用适合页面的资源字典,以避免不必要的搜索。
概述
本文介绍了如何创建和使用ResourceDictionary,以及如何合并资源字典。 ResourceDictionary允许在单个位置定义资源,并在整个Xamarin.Forms应用程序中重新使用。