Tworzenie spójnego interfejsu użytkownika przy użyciu stylów

Ukończone

Zasoby doskonale nadają się do unikania zakodowanych trwale, zduplikowanych wartości w znacznikach XAML, ale mogą być żmudne do zastosowania. Każda wartość właściwości jest przypisywana indywidualnie, co może spowodować zaśmiecone i pełne kod XAML. W tej lekcji pokazano, jak pogrupować wiele ustawień w styl, co może pomóc w declutter kodu i zwiększyć jego obsługę.

Jak zasoby mogą zaśmiecać kod XAML

Zasób zapewnia wartość pojedynczej właściwości. Jednak użycie wielu zasobów może prowadzić do pełnego kodu XAML. Załóżmy, że chcesz dostosować wygląd przycisków. Najpierw należy utworzyć zasoby dla potrzebnych wartości. Następnie zastosujesz każdy zasób do wszystkich przycisków. Poniższy kod pokazuje, jak znaczniki XAML mogą szukać dwóch przycisków.

<Button
    Text = "OK"
    BackgroundColor = "{StaticResource highlightColor}"
    BorderColor = "{StaticResource borderColor}"
    BorderWidth = "{StaticResource borderWidth}"
    TextColor = "{StaticResource textColor}" />

<Button
    Text = "Cancel"
    BackgroundColor = "{StaticResource highlightColor}"
    BorderColor = "{StaticResource borderColor}"
    BorderWidth = "{StaticResource borderWidth}"
    TextColor = "{StaticResource textColor}" />

Zwróć uwagę, że te same pięć właściwości jest ustawionych na każdym z przycisków. Użycie zasobów eliminuje potrzebę powtarzających się, zakodowanych na kodzie wartości w czterech z nich. Jednak ten typ znaczników XAML szybko staje się trudny do odczytania. Ponadto jeśli ustawiasz dużą liczbę właściwości dla każdej kontrolki, łatwo jest przypadkowo pominąć jedną z nich, co prowadzi do niespójności w wyglądzie kontrolek. Rozwiązaniem jest utworzenie stylu, który przypisuje wszystkie cztery właściwości jednocześnie.

Co to jest zestaw?

Moduły ustawiania to kluczowe składniki używane do tworzenia stylów.

Setter to kontener dla pary właściwości/wartości. Można traktować element ustawiający jako reprezentujący instrukcję przypisania. Należy określić, która właściwość ma zostać przypisana, oraz wartość do zastosowania. Zazwyczaj obiekty Setter są tworzone w znacznikach XAML. Poniższy przykład tworzy obiekt Setter dla właściwości TextColor .

<Setter Property="TextColor" Value="White" />

Możesz użyć zasobu dla wartości w metodzie ustawiającej, jak pokazano w poniższym kodzie. Ta technika jest świetna, gdy chcesz użyć tej samej wartości w wielu zestawach.

<Setter Property="TextColor" Value="{StaticResource textColor}" />

Uwaga

Wartość właściwości określona w zestawie musi być zaimplementowana jako właściwość powiązana. Wszystkie właściwości kontrolek w programie .NET MAUI kończące się właściwością sufiksu są właściwościami, które można powiązać. Jeśli próbujesz użyć właściwości, takiej jak TextColor w ustawieniu, upewnij się, że dla tej kontrolki istnieje odpowiednia właściwość z możliwością powiązania o nazwie TextColorProperty. W praktyce prawie wszystkie właściwości, których chcesz używać w zestawach, są implementowane w ten sposób.

Co to jest styl?

Styl to kolekcja zestawów przeznaczonych dla określonego typu kontrolki. Program .NET MAUI wymaga typu docelowego, aby upewnić się, że właściwości w zestawerach istnieją w tym typie.

Poniższy kod przedstawia styl, który łączy cztery wartości z poprzedniego przykładu. Zwróć uwagę, że właściwość TargetType jest ustawiona na Przycisk, a wszystkie właściwości w setterach są elementami członkowskimi klasy Button. Nie można użyć tego stylu dla etykiety, ponieważ klasa Label nie zawiera właściwości BorderColor ani BorderWidth .

<Style TargetType="Button">
    <Setter Property="BackgroundColor" Value="#2A84D3" />
    <Setter Property="BorderColor" Value="#1C5F9B" />
    <Setter Property="BorderWidth" Value="3" />
    <Setter Property="TextColor" Value="White" />
</Style>

Definiowanie stylu

Zazwyczaj style są definiowane jako zasoby wewnątrz obiektu ResourceDictionary . Słownik zasobów ułatwia używanie stylu między wieloma kontrolkami na tej samej stronie, a nawet w całej aplikacji. Poniższy kod pokazuje, jak zdefiniować styl jako zasób w słowniku. Zwróć uwagę, że styl ma nazwę przy użyciu właściwości x:Key . Nazewnictwo stylu umożliwia odwołowanie się do niego z poziomu stron XAML.

<ContentPage.Resources>
    <Style x:Key="MyButtonStyle" TargetType="Button">
        ...
    </Style>
</ContentPage.Resources>

Stosowanie stylu

Styl jest dołączany do kontrolki, przypisując nazwę do właściwości Style . Przypisanie powoduje, że każdy z obiektów Setter w stylu ma być stosowany do kontrolki docelowej. Poniższy kod pokazuje, jak zastosować styl przycisku do dwóch przycisków.

<Button Text="OK" Style="{StaticResource MyButtonStyle}" />
<Button Text="Cancel" Style="{StaticResource MyButtonStyle}" />

W poprzednim przykładzie użyto rozszerzenia znacznika StaticResource , aby dołączyć styl do kontrolek. Ta technika jest świetna, gdy styl nie jest potrzebny do zmiany w czasie wykonywania. Ale co zrobić, jeśli chcesz zaimplementować coś takiego jak motywy dynamiczne, gdzie interfejs użytkownika musi ulec zmianie? W takim przypadku możesz użyć rozszerzenia DynamicResource mark-up, aby załadować styl.

<Button Text="Cancel" Style="{DynamicResource MyButtonStyle}" />

DynamicResource nasłuchuje zamiany właściwości x:Key w słowniku zasobów. Jeśli napiszesz kod, który ładuje nowy styl do elementu ResourceDictionary z tą samą wartością x:Key , nowy styl zostanie automatycznie zastosowany do interfejsu użytkownika.

Używanie niejawnego stylu dla wielu kontrolek

Załóżmy, że interfejs użytkownika ma 50 przycisków i chcesz zastosować ten sam styl do wszystkich z nich. Z tym, co wiemy do tej pory, należy ręcznie przypisać do właściwości Style na każdym przycisku. To nie jest tak trudne do zrobienia, ale nadal jest żmudne.

Niejawny styl to styl dodany do słownika zasobów bez podawania mu identyfikatora x:Key . Style niejawne są automatycznie stosowane do wszystkich kontrolek określonego obiektu TargetType .

Poniższy kod przedstawia poprzedni przykład zadeklarowany jako niejawny styl. Ten styl jest stosowany do każdego przycisku na stronie.

<ContentPage.Resources>
    <Style TargetType="Button">
        <Setter Property="BackgroundColor" Value="Blue" />
        <Setter Property="BorderColor" Value="Navy" />
        ...
    </Style>
</ContentPage.Resources>

Ważne

Dopasowanie niejawnych stylów do kontrolek wymaga dokładnego dopasowania do określonego typu TargetType. Kontrolki dziedziczone z typu docelowego nie będą otrzymywać stylów. Aby wpłynąć na dziedziczone kontrolki, można ustawić atrybut Style.ApplyToDerivedTypes na wartość True podczas definiowania stylu. Aby na przykład zastosować styl do typu Przycisk i mieć wpływ na dowolny z przycisków dziedziczynych z przycisku (takich jak ImageButton, RadioButton lub utworzony typ niestandardowy), możesz użyć stylu takiego jak ten.

<ContentPage.Resources>
    <Style TargetType="Button"
           ApplyToDerivedTypes="True">
        <Setter Property="BackgroundColor" Value="Black" />
    </Style>
</ContentPage.Resources>

Zastępowanie stylu

Styl można traktować jako dostarczający zestaw wartości domyślnych dla kontrolek. Istniejący styl może być zbliżony do wymagań, ale zawierać jeden lub dwa zestawy, których nie chcesz. W takim przypadku można zastosować styl, a następnie zastąpić wartość, ustawiając właściwości bezpośrednio. Jawne ustawienie jest stosowane po stylu, więc zastąpi wartość z stylu.

Załóżmy, że chcesz użyć następującego stylu dla kilku przycisków na stronie.

<Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="BackgroundColor" Value="Blue" />
    <Setter Property="BorderRadius" Value="10" />
    <Setter Property="BorderWidth" Value="3" />
</Style>

Ten styl działa dla wszystkich przycisków z wyjątkiem Przycisku Anuluj, który wymaga czerwonego tła. Możesz użyć tego samego stylu dla przycisku Anuluj, o ile ustawisz również właściwość BackgroundColor bezpośrednio. Poniższy kod pokazuje, jak zastąpić ustawienie koloru.

<Button
    Text="Cancel"
    Style="{StaticResource MyButtonStyle}"
    BackgroundColor="Red"
    ... />

Określanie elementu docelowego typu obiektu przodka

Załóżmy, że chcesz uzyskać niestandardowy kolor tła dla przycisków i etykiet. Możesz utworzyć oddzielne style dla każdego typu lub utworzyć jeden styl z typem TargetType ustawionym na Element VisualElement. Ta technika działa, ponieważ VisualElement jest klasą bazową zarówno dla przycisku, jak i etykiety.

Poniższy kod przedstawia styl, który jest przeznaczony dla klasy bazowej stosowanej do dwóch różnych typów pochodnych.

<Style x:Key="MyVisualElementStyle" TargetType="VisualElement">
    <Setter Property="BackgroundColor" Value="#2A84D3" />
</Style>
...
<Button Style="{StaticResource MyVisualElementStyle}" ... />
<Label Style="{StaticResource MyVisualElementStyle}" ... />

W tym przykładzie określono styl przy użyciu x:Key , a kontrolki są stosowane jawnie. Niejawny styl nie działa tutaj, ponieważ typ TargetType dla stylu niejawnego musi być dokładnym dopasowaniem do typu kontrolki.

Używanie funkcji BasedOn do dziedziczenia po stylu

Załóżmy, że chcesz utworzyć spójny wygląd interfejsu użytkownika. Decydujesz, że wszystkie kontrolki powinny używać spójnego koloru tła. Ustawienie koloru tła może pojawić się w więcej niż jednym ze stylów. Poniższy kod przedstawia dwa style z powtarzającym się zestawem.

<Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="BackgroundColor" Value="Blue" />
    <Setter Property="BorderColor" Value="Navy" />
    <Setter Property="BorderWidth" Value="5" />
</Style>

<Style x:Key="MyEntryStyle" TargetType="Entry">
    <Setter Property="BackgroundColor" Value="Blue" />
    <Setter Property="TextColor" Value="White" />
</Style>

Możesz użyć dziedziczenia stylów, aby uwzględnić zduplikowany zestaw do stylu podstawowego. Aby utworzyć styl pochodny, ustaw jej właściwość BasedOn , aby odwoływać się do stylu podstawowego. Nowy styl dziedziczy wszystkie zestawy ze swojego stylu podstawowego. Styl pochodny może również dodawać nowe zestawy lub zastępować dziedziczony setter elementem zawierającym inną wartość.

Poniższy kod przedstawia poprzednie przykładowe style refaktoryzowane w hierarchii. Wspólny zestaw jest wyświetlany tylko w stylu podstawowym, a nie powtarzany. Zwróć uwagę, że używasz rozszerzenia staticResource mark-up, aby wyszukać styl podstawowy. W tej sytuacji nie można użyć usługi DynamicResource .

<Style x:Key="MyVisualElementStyle" TargetType="VisualElement">
    <Setter Property="BackgroundColor" Value="Blue" />
</Style>

<Style x:Key="MyButtonStyle" TargetType="Button" BasedOn="{StaticResource MyVisualElementStyle}">
    <Setter Property="BorderColor" Value="Navy" />
    <Setter Property="BorderWidth" Value="5" />
</Style>

<Style x:Key="MyEntryStyle" TargetType="Entry" BasedOn="{StaticResource MyVisualElementStyle}">
    <Setter Property="TextColor" Value="White" />
</Style>

Wartość TargetType stylów podstawowych i pochodnych musi być zgodna. Aby style były zgodne, muszą mieć tę samą właściwość TargetType lub typ TargetType stylu pochodnego jest malejącym elementem TargetType stylu podstawowego.

Test wiedzy

1.

Dlaczego należy zdefiniować styl w obiekcie ResourceDictionary?

Sprawdź swoje odpowiedzi