Xamarin.Forms での動的スタイル
スタイルはプロパティの変更に応答しません。アプリケーションの期間中は変更されないままです。 たとえば、スタイルをビジュアル要素に割り当てた後、Setter インスタンスのいずれかが変更された、削除された、または新しい Setter インスタンスが追加された場合、変更はビジュアル要素に適用されません。 ただし、アプリケーションは、動的リソースを使って実行時にスタイルの変更に動的に応答できます。
DynamicResource
マークアップ拡張と StaticResource
マークアップ拡張は、両方ともディクショナリ キーを使用して ResourceDictionary
から値を取得するという点で、似ています。 ただし、StaticResource
が 1 回だけディクショナリ検索を実行するのに対して、DynamicResource
はディクショナリ キーへのリンクを保持します。 そのため、キーに関連付けられているディクショナリ エントリが置き換えられると、その変更がビジュアル要素に適用されます。 これにより、実行時のスタイルの変更をアプリケーションで行うことができます。
次のコード例は、XAML ページの "動的" スタイルを示しています。
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.DynamicStylesPage" Title="Dynamic" IconImageSource="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="baseStyle" TargetType="View">
...
</Style>
<Style x:Key="blueSearchBarStyle"
TargetType="SearchBar"
BasedOn="{StaticResource baseStyle}">
...
</Style>
<Style x:Key="greenSearchBarStyle"
TargetType="SearchBar">
...
</Style>
...
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<SearchBar Placeholder="These SearchBar controls"
Style="{DynamicResource searchBarStyle}" />
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
SearchBar
インスタンスは、DynamicResource
マークアップ拡張機能を使って、XAML で定義されていない searchBarStyle
という Style
を参照します。 ただし、SearchBar
インスタンスの Style
プロパティは DynamicResource
を使って設定されているため、ディクショナリ キーが欠落していても例外はスローされません。
代わりに、次のコード例に示すように、キー searchBarStyle
を持つ ResourceDictionary
エントリがコンストラクターによって分離コード ファイル内に作成されます。
public partial class DynamicStylesPage : ContentPage
{
bool originalStyle = true;
public DynamicStylesPage ()
{
InitializeComponent ();
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
}
void OnButtonClicked (object sender, EventArgs e)
{
if (originalStyle) {
Resources ["searchBarStyle"] = Resources ["greenSearchBarStyle"];
originalStyle = false;
} else {
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
originalStyle = true;
}
}
}
OnButtonClicked
イベント ハンドラーが実行されると、searchBarStyle
は blueSearchBarStyle
と greenSearchBarStyle
の間で切り替わります。 これで、次のスクリーンショットのような結果になります。
次のコード例は、C# の同等のページを示しています。
public class DynamicStylesPageCS : ContentPage
{
bool originalStyle = true;
public DynamicStylesPageCS ()
{
...
var baseStyle = new Style (typeof(View)) {
...
};
var blueSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
var greenSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
...
var searchBar1 = new SearchBar { Placeholder = "These SearchBar controls" };
searchBar1.SetDynamicResource (VisualElement.StyleProperty, "searchBarStyle");
...
Resources = new ResourceDictionary ();
Resources.Add ("blueSearchBarStyle", blueSearchBarStyle);
Resources.Add ("greenSearchBarStyle", greenSearchBarStyle);
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
Content = new StackLayout {
Children = { searchBar1, searchBar2, searchBar3, searchBar4, button }
};
}
...
}
C# では、SearchBar
インスタンスは SetDynamicResource
メソッドを使って searchBarStyle
を参照します。 OnButtonClicked
イベント ハンドラー コードは XAML の例と同じであり、実行すると、searchBarStyle
は blueSearchBarStyle
と greenSearchBarStyle
の間で切り替わります。
動的スタイルの継承
Style.BasedOn
プロパティを使用して動的スタイルからスタイルを派生させることはできません。 代わりに、Style
クラスには BaseResourceKey
プロパティが含まれており、このプロパティを、値が動的に変更される可能性があるディクショナリ キーに設定できます。
次のコード例は、XAML ページの "動的" スタイルの継承を示しています。
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.DynamicStylesInheritancePage" Title="Dynamic Inheritance" IconImageSource="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="baseStyle" TargetType="View">
...
</Style>
<Style x:Key="blueSearchBarStyle" TargetType="SearchBar" BasedOn="{StaticResource baseStyle}">
...
</Style>
<Style x:Key="greenSearchBarStyle" TargetType="SearchBar">
...
</Style>
<Style x:Key="tealSearchBarStyle" TargetType="SearchBar" BaseResourceKey="searchBarStyle">
...
</Style>
...
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<SearchBar Text="These SearchBar controls" Style="{StaticResource tealSearchBarStyle}" />
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
SearchBar
インスタンスは、StaticResource
マークアップ拡張機能を使って、tealSearchBarStyle
という Style
を参照します。 この Style
は、いくつかの追加のプロパティを設定し、BaseResourceKey
プロパティを使用して searchBarStyle
を参照します。 DynamicResource
マークアップ拡張は必要ありません。派生元の Style
を除き、tealSearchBarStyle
が変更されないからです。 そのため、tealSearchBarStyle
は searchBarStyle
へのリンクを維持し、基本スタイルが変わると変更されます。
動的スタイルを示した前の例に従って、分離コード ファイルのコンストラクターでキー searchBarStyle
を持つ ResourceDictionary
エントリを作成します。 OnButtonClicked
イベント ハンドラーが実行されると、searchBarStyle
は blueSearchBarStyle
と greenSearchBarStyle
の間で切り替わります。 これで、次のスクリーンショットのような結果になります。
次のコード例は、C# の同等のページを示しています。
public class DynamicStylesInheritancePageCS : ContentPage
{
bool originalStyle = true;
public DynamicStylesInheritancePageCS ()
{
...
var baseStyle = new Style (typeof(View)) {
...
};
var blueSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
var greenSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
var tealSearchBarStyle = new Style (typeof(SearchBar)) {
BaseResourceKey = "searchBarStyle",
...
};
...
Resources = new ResourceDictionary ();
Resources.Add ("blueSearchBarStyle", blueSearchBarStyle);
Resources.Add ("greenSearchBarStyle", greenSearchBarStyle);
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
Content = new StackLayout {
Children = {
new SearchBar { Text = "These SearchBar controls", Style = tealSearchBarStyle },
...
}
};
}
...
}
tealSearchBarStyle
は、SearchBar
インスタンスの Style
プロパティに直接割り当てられます。 この Style
でいくつかの追加プロパティを設定し、BaseResourceKey
プロパティを使って searchBarStyle
を参照します。 派生元の Style
を除いて tealSearchBarStyle
は変更されないため、ここでは SetDynamicResource
メソッドは必要ありません。 そのため、tealSearchBarStyle
は searchBarStyle
へのリンクを維持し、基本スタイルが変わると変更されます。