Dynamische Formatvorlagen in Xamarin.Forms

Formatvorlagen reagieren nicht auf Eigenschaftsänderungen und ändern Standard für die Dauer einer Anwendung unverändert. Wenn beispielsweise eine der Setter-Instanzen geändert, entfernt oder eine neue Setter-Instanz hinzugefügt wurde, werden die Änderungen nicht auf das visuelle Element angewendet, nachdem sie einem visuellen Element eine Formatvorlage zugewiesen haben. Anwendungen können jedoch dynamisch auf Stiländerungen zur Laufzeit reagieren, indem sie dynamische Ressourcen verwenden.

Die DynamicResource-Markuperweiterung ähnelt der StaticResource-Markuperweiterung insofern ähnlich, als beide einen Wörterbuchschlüssel verwenden, um einen Wert aus einem ResourceDictionary zu extrahieren. Während die StaticResource jedoch nur eine einzige Wörterbuchabfrage durchführt, behält die DynamicResource eine Verknüpfung zum Wörterbuchschlüssel bei. Wenn also der mit dem Schlüssel verknüpfte Wörterbucheintrag ersetzt wird, wird die Änderung auf das visuelle Element angewendet. Dadurch können Laufzeitstiländerungen in einer Anwendung vorgenommen werden.

Im folgenden Codebeispiel werden dynamische Formatvorlagen auf einer XAML-Seite veranschaulicht:

<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>

Die SearchBar Instanzen verwenden die DynamicResource Markuperweiterung, um auf einen Style benannten searchBarStyleNamen zu verweisen, der im XAML-Code nicht definiert ist. Da jedoch die Style Eigenschaften der SearchBar Instanzen mit einem DynamicResourcefestgelegt werden, führt der fehlende Wörterbuchschlüssel nicht zu einer Ausnahme, die ausgelöst wird.

Stattdessen erstellt der Konstruktor in der CodeBehind-Datei einen ResourceDictionary Eintrag mit dem Schlüssel searchBarStyle, wie im folgenden Codebeispiel gezeigt:

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;
        }
    }
}

Wenn der OnButtonClicked Ereignishandler ausgeführt wird, searchBarStyle wechselt zwischen blueSearchBarStyle und greenSearchBarStyle. Dies ergibt die in den folgenden Screenshots gezeigte Darstellung:

Beispiel für eine blaue dynamische FormatvorlageBeispiel für eine grüne dynamische Formatvorlage

Im folgenden Codebeispiel wird die entsprechende Seite in C# veranschaulicht:

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    }
        };
    }
    ...
}

In C# verwenden die Instanzen die SearchBarSetDynamicResource Methode, um auf sie zu verweisen searchBarStyle. Der OnButtonClicked Ereignishandlercode ist identisch mit dem XAML-Beispiel, und wenn er ausgeführt wird, searchBarStyle wechselt zwischen blueSearchBarStyle und greenSearchBarStyle.

Vererbung dynamischer Stile

Die Ableitung eines Stils aus einem dynamischen Stil ist mit der Eigenschaft Style.BasedOn nicht möglich. Stattdessen enthält die Style-Klasse die Eigenschaft BaseResourceKey, die auf einen Wörterbuchschlüssel gesetzt werden kann, dessen Wert sich dynamisch ändern kann.

Im folgenden Codebeispiel wird die Vererbung dynamischer Stile auf einer XAML-Seite veranschaulicht:

<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>

Die SearchBar Instanzen verwenden die StaticResource Markuperweiterung, um auf einen Style benannten Namen tealSearchBarStylezu verweisen. Dieser Style definiert einige zusätzliche Eigenschaften und verwendet die BaseResourceKey-Eigenschaft, um auf searchBarStyle zu verweisen. Die DynamicResource-Markuperweiterung ist nicht erforderlich, da tealSearchBarStyle unverändert bleibt, mit Ausnahme von Style, von dem es abgeleitet ist. Daher Standard eine Verknüpfung searchBarStyle zu und wird geändert, tealSearchBarStyle wenn sich die Basisformatvorlage ändert.

In der CodeBehind-Datei erstellt der Konstruktor einen ResourceDictionary Eintrag mit dem Schlüssel searchBarStylegemäß dem vorherigen Beispiel, in dem dynamische Formatvorlagen veranschaulicht wurden. Wenn der OnButtonClicked Ereignishandler ausgeführt wird, searchBarStyle wechselt zwischen blueSearchBarStyle und greenSearchBarStyle. Dies ergibt die in den folgenden Screenshots gezeigte Darstellung:

Beispiel für die Vererbung der dynamischen BlauformatvorlageBeispiel für die Vererbung dynamischer Formatvorlagen

Im folgenden Codebeispiel wird die entsprechende Seite in C# veranschaulicht:

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 },
                ...
            }
        };
    }
    ...
}

Die tealSearchBarStyle Eigenschaft der SearchBar Instanzen wird direkt Style zugewiesen. Dadurch Style werden einige zusätzliche Eigenschaften festgelegt und die BaseResourceKey Eigenschaft verwendet, um auf sie zu verweisen searchBarStyle. Die SetDynamicResource Methode ist hier nicht erforderlich, da tealSearchBarStyle sich dies nicht ändert, mit Ausnahme der Style abgeleiteten Methode. Daher Standard eine Verknüpfung searchBarStyle zu und wird geändert, tealSearchBarStyle wenn sich die Basisformatvorlage ändert.

Auf Channel 9 und auf YouTube finden Sie weitere Videos zu Xamarin.