Динамические стили в Xamarin.Forms
Стили не реагируют на изменения свойств и остаются неизменными в течение длительности приложения. Например, после назначения стиля визуальному элементу, если один из экземпляров Setter изменен, удален или добавлен новый экземпляр Setter, изменения не будут применены к визуальному элементу. Однако приложения могут динамически реагировать на изменения стиля во время выполнения с помощью динамических ресурсов.
DynamicResource
Расширение разметки аналогично StaticResource
расширению разметки в том, что оба используют ключ словаря для получения значения изResourceDictionary
. Однако при выполнении StaticResource
одного поиска словаря 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
используют расширение разметки для ссылки на именованный searchBarStyle
DynamicResource
Style
объект, который не определен в XAML. Однако, поскольку Style
свойства SearchBar
экземпляров задаются с помощью DynamicResource
ключа, отсутствующий ключ словаря не приводит к возникновению исключения.
Вместо этого в файле программной части конструктор создает ResourceDictionary
запись с ключом searchBarStyle
, как показано в следующем примере кода:
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;
}
}
}
При выполнении searchBarStyle
обработчика OnButtonClicked
событий переключится между 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
Расширение разметки не требуется, так как tealSearchBarStyle
не изменится, за исключением Style
производных от него расширений. tealSearchBarStyle
Поэтому сохраняет ссылку на searchBarStyle
и изменяется при изменении базового стиля.
В файле программной части конструктор создает ResourceDictionary
запись с ключом searchBarStyle
, как показано в предыдущем примере, демонстрирующем динамические стили. При выполнении searchBarStyle
обработчика OnButtonClicked
событий переключится между 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
назначается непосредственно свойству Style
SearchBar
экземпляров. При этом Style
задаются некоторые дополнительные свойства и используется BaseResourceKey
свойство для ссылки searchBarStyle
. Этот SetDynamicResource
метод не требуется, так как tealSearchBarStyle
он не изменится, за исключением Style
производных от него. tealSearchBarStyle
Поэтому сохраняет ссылку на searchBarStyle
и изменяется при изменении базового стиля.