动态样式
Style通常是一个静态对象,它在XAML或代码中创建和初始化,然后在应用程序的持续时间内保持不变。 Style类不是从BindableOb?ject派生的,也不在内部响应其属性的变化。 例如,如果将Style对象分配给元素,然后通过为其设置新值来修改其中一个Setter对象,则新值将不会显示在元素中。 同样,如果添加Setter或从Setters集合中删除Setter,则target元素不会更改。 要使这些新属性设置器生效,您需要使用代码通过将Style属性设置为null来将该样式与该元素分离,然后将该样式重新附加到该元素。
但是,您的应用程序可以通过使用DynamicResource在运行时动态响应样式更改。您会记得DynamicResource类似于StaticResource,因为它使用字典键从资源字典中获取对象或值。不同之处在于StaticResource是一次性字典查找,而DynamicResource维护到实际字干键的链接。如果与该键关联的词典条目被替换为新对象,则该更改为
传播到元素。
此工具允许应用程序实现有时称为动态样式的功能。例如,您可以在程序中包含一个用于样式主题的设施(涉及字体和颜色,每个人),您可以使这些主题可由用户选择。应用程序可以在这些主题之间切换,因为它们是使用样式实现的。
样式本身没有任何东西表明动态风格。样式仅通过使用DynamicResource而不是StaticResource引用而变为动态。
DynamicStyles项目演示了此过程的机制。这是DynamicStylesPage类的XAML文件:
-
<ContentPage xmlns=""
-
xmlns:x=""
-
x:Class="DynamicStyles.DynamicStylesPage">
-
<ContentPage.Padding>
-
<OnPlatform x:TypeArguments="Thickness"
-
iOS="0, 20, 0, 0"
-
Android="0"
-
WinPhone="0" />
-
</ContentPage.Padding>
-
<ContentPage.Resources>
-
<ResourceDictionary>
-
<Style x:Key="baseButtonStyle" TargetType="Button">
-
<Setter Property="FontSize" Value="Large" />
-
</Style>
-
-
<Style x:Key="buttonStyle1" TargetType="Button"
-
BasedOn="{StaticResource baseButtonStyle}">
-
<Setter Property="HorizontalOptions" Value="Center" />
-
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
-
<Setter Property="TextColor" Value="Red" />
-
</Style>
-
<Style x:Key="buttonStyle2" TargetType="Button"
-
BasedOn="{StaticResource baseButtonStyle}">
-
<Setter Property="HorizontalOptions" Value="Start" />
-
<Setter Property="VerticalOptions" Value="EndAndExpand" />
-
<Setter Property="TextColor" Value="Green" />
-
<Setter Property="FontAttributes" Value="Italic" />
-
</Style>
-
<Style x:Key="buttonStyle3" TargetType="Button"
-
BasedOn="{StaticResource baseButtonStyle}">
-
<Setter Property="HorizontalOptions" Value="End" />
-
<Setter Property="VerticalOptions" Value="StartAndExpand" />
-
<Setter Property="TextColor" Value="Blue" />
-
<Setter Property="FontAttributes" Value="Bold" />
-
</Style>
-
</ResourceDictionary>
-
</ContentPage.Resources>
-
<StackLayout>
-
<Button Text=" Switch to Style #1 "
-
Style="{DynamicResource buttonStyle}"
-
Clicked="OnButton1Clicked" />
-
<Button Text=" Switch to Style #2 "
-
Style="{DynamicResource buttonStyle}"
-
Clicked="OnButton2Clicked" />
-
-
<Button Text=" Switch to Style #3 "
-
Style="{DynamicResource buttonStyle}"
-
Clicked="OnButton3Clicked" />
-
<Button Text=" Reset "
-
Style="{DynamicResource buttonStyle}"
-
Clicked="OnResetButtonClicked" />
-
</StackLayout>
-
</ContentPage>
参考资料部分定义了四种样式:一个简单的样式,键为“baseButtonStyle”,然后是三个样式,派生自该样式,键为“buttonStyle1”,“buttonStyle2”和“buttonStyle3”。
但是,XAML文件底部的四个Button元素都使用DynamicResource来引用具有更简单键“buttonStyle”的样式。 带有那把钥匙的Style在哪里? 它不存在。 但是,因为使用DynamicResource设置了四个按钮样式属性,所以缺少的字典键不是问题。 没有例外。 但是没有应用Style,这意味着按钮具有默认外观:
四个Button元素中的每一个都附加了一个Clicked处理程序,并且在代码隐藏文件中,前三个处理程序将一个字典条目与键“buttonStyle”设置为已在字典中定义的三个编号样式之一:
-
public partial class DynamicStylesPage : ContentPage
-
{
-
public DynamicStylesPage()
-
{
-
InitializeComponent();
-
}
-
void OnButton1Clicked(object sender, EventArgs args)
-
{
-
Resources["buttonStyle"] = Resources["buttonStyle1"];
-
}
-
void OnButton2Clicked(object sender, EventArgs args)
-
{
-
Resources["buttonStyle"] = Resources["buttonStyle2"];
-
}
-
void OnButton3Clicked(object sender, EventArgs args)
-
{
-
Resources["buttonStyle"] = Resources["buttonStyle3"];
-
}
-
void OnResetButtonClicked(object sender, EventArgs args)
-
{
-
Resources["buttonStyle"] = null;
-
}
-
}
按下前三个按钮之一时,所有四个按钮都将获得所选样式。 这是在所有三个平台上运行的程序,显示按下按钮1,2和3时的结果(从左到右):
按第四个按钮可将所有与“buttonStyle”键相关联的值设置为null,从而将所有内容返回到初始条件。 (您可能还会考虑在Re?sourceDictionary对象上调用Remove或Clear来完全删除密钥,但这在本章使用的Xama?rin.Forms版本中不起作用。)
假设您要使用键“buttonStyle”从样式派生另一个样式。 考虑到在按下前三个按钮之一后“buttonStyle”字典条目不存在,你如何在XAML中执行此操作?
你不能这样做:
-
<Style x:Key="newButtonStyle" TargetType="Button"
-
BasedOn="{StaticResource buttonStyle}">
-
...
-
</Style>
如果“buttonStyle”键不存在,StaticResource将引发异常,即使密钥确实存在,StaticResource的使用也不允许字典条目中的更改反映在此新样式中。
但是,将StaticResource更改为DynamicResource也不起作用:
-
<Style x:Key="newButtonStyle" TargetType="Button"
-
BasedOn="{DynamicResource buttonStyle}">
-
...
-
</Style>
DynamicResource仅适用于可绑定属性支持的属性,而这不是这种情况。 Style不是从BindableObject派生的,因此它不支持可绑定属性。
相反,Style定义了一个专门用于继承动态样式的属性。 该属性是BaseResourceKey,它旨在直接设置为可能尚不存在或其值可能动态更改的字典键,“buttonStyle”键就是这种情况:
-
<Style x:Key="newButtonStyle" TargetType="Button"
-
BaseResourceKey="buttonStyle">
-
...
-
</Style>
DynamicStylesInheritance项目演示了BaseResourceKey的使用,它与DynamicStyles项目非常相似。 实际上,代码隐藏处理是相同的。 在Resources部分的底部,使用“newButtonStyle”键定义一个新Style,它使用BaseResourceKey引用“buttonStyle”条目并添加一些属性,包括使用OnPlatform的属性:
-
<ContentPage xmlns=""
-
xmlns:x=""
-
x:Class="DynamicStylesInheritance.DynamicStylesInheritancePage">
-
<ContentPage.Padding>
-
<OnPlatform x:TypeArguments="Thickness"
-
iOS="0, 20, 0, 0"
-
Android="0"
-
WinPhone="0" />
-
</ContentPage.Padding>
-
<ContentPage.Resources>
-
<ResourceDictionary>
-
<Style x:Key="baseButtonStyle" TargetType="Button">
-
<Setter Property="FontSize" Value="Large" />
-
</Style>
-
<Style x:Key="buttonStyle1" TargetType="Button"
-
BasedOn="{StaticResource baseButtonStyle}">
-
<Setter Property="HorizontalOptions" Value="Center" />
-
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
-
<Setter Property="TextColor" Value="Red" />
-
</Style>
-
<Style x:Key="buttonStyle2" TargetType="Button"
-
BasedOn="{StaticResource baseButtonStyle}">
-
<Setter Property="HorizontalOptions" Value="Start" />
-
<Setter Property="VerticalOptions" Value="EndAndExpand" />
-
<Setter Property="TextColor" Value="Green" />
-
<Setter Property="FontAttributes" Value="Italic" />
-
</Style>
-
<Style x:Key="buttonStyle3" TargetType="Button"
-
BasedOn="{StaticResource baseButtonStyle}">
-
<Setter Property="HorizontalOptions" Value="End" />
-
<Setter Property="VerticalOptions" Value="StartAndExpand" />
-
<Setter Property="TextColor" Value="Blue" />
-
<Setter Property="FontAttributes" Value="Bold" />
-
</Style>
-
<!-- New style definition. -->
-
<Style x:Key="newButtonStyle" TargetType="Button"
-
BaseResourceKey="buttonStyle">
-
<Setter Property="BackgroundColor">
-
<Setter.Value>
-
<OnPlatform x:TypeArguments="Color"
-
iOS="#C0C0C0"
-
Android="#404040"
-
WinPhone="Gray" />
-
</Setter.Value>
-
</Setter>
-
<Setter Property="BorderColor" Value="Red" />
-
<Setter Property="BorderWidth" Value="3" />
-
</Style>
-
</ResourceDictionary>
-
</ContentPage.Resources>
-
<StackLayout>
-
<Button Text=" Switch to Style #1 "
-
Style="{StaticResource newButtonStyle}"
-
Clicked="OnButton1Clicked" />
-
<Button Text=" Switch to Style #2 "
-
Style="{StaticResource newButtonStyle}"
-
Clicked="OnButton2Clicked" />
-
<Button Text=" Switch to Style #3 "
-
Style="{StaticResource newButtonStyle}"
-
Clicked="OnButton3Clicked" />
-
<Button Text=" Reset "
-
Style="{DynamicResource buttonStyle}"
-
Clicked="OnResetButtonClicked" />
-
</StackLayout>
-
</ContentPage>
请注意,前三个Button元素引用带有StaticResource的“newButtonStyle”字典条目。 这里不需要DynamicResource,因为与“newButtonStyle”关联的Style对象本身不会改变,除了它派生的Style。 具有键“newButtonStyle”的Style保持与“buttonStyle”的链接,并在该un-derlying样式发生变化时在内部改变。 当程序开始运行时,只有“newButtonStyle”中定义的属性才会应用于这三个按钮:
“重置”按钮继续引用“buttonStyle”条目。
与DynamicStyles程序一样,代码隐藏文件在您单击前三个按钮之一时设置该字典条目,因此所有按钮也会选择“buttonStyle”属性。 以下是按钮3,2和1的(从左到右)点击的结果:
阅读(5342) | 评论(0) | 转发(0) |