Wednesday, 16 May 2018

Dynamic Resource

If you want to update a xaml resource at run time, this can be done using a {DynamicResouce} binding. take a look at our view

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:pav00.DynamicResouceExample"
             x:Class="pav00.DynamicResouceExample.MainPage">

    <ContentPage.Resources>
        <ResourceDictionary>
            <Color x:Key="HighlightColor">Red</Color>
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>
        <Label Text="Welcome to Xamarin.Forms!" 
               BackgroundColor="{DynamicResource HighlightColor}"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <Button x:Name="Red_Button" Clicked="Color_Toggled" Text="Red"
                TextColor="{DynamicResource HighlightColor}" />
        <Button x:Name="Green_Button" Clicked="Color_Toggled" Text="Green" />
        <Button x:Name="Blue_Button" Clicked="Color_Toggled" Text="Blue"  />
    </StackLayout>
</ContentPage>


pretty straight forward, notice that we create a normal resource dictionary with one value for Color in it, we then do a {DynamicResource} binding instead of a {StaticResource} binding, this is what will allow us to then update the value of our HighlighteColor resource from code.

public partial class MainPage : ContentPage
{
    public MainPage() => InitializeComponent();

    private void Color_Toggled(object sender, ToggledEventArgs e)
    {
        var button = sender as Button;
        var buttons = new[] { Red_Button, Green_Button, Blue_Button };
        switch (button.Text.ToLower())
        {
            case "red":
                this.Resources["HighlightColor"] = new Color(255, 0, 0);
                break;
            case "green":
                this.Resources["HighlightColor"] = new Color(0, 255, 0);
                break;
            case "blue":
                this.Resources["HighlightColor"] = new Color(0, 0, 255);
                break;
        }

        foreach (var btn in buttons)
        {
            btn.TextColor = Color.Default;
            btn.RemoveDynamicResource(Button.TextColorProperty);
        }
        button.SetDynamicResource(Button.TextColorProperty, "HighlightColor");
    }

}

and that's all that there's to it,

  • we can update the resource dictionary by simply referring to the item inside it by the key and assigning it a different value.
  • we can remove a reference to the resource using the RemoveDynamicResouce attached property 
  • we can set a resource using the SetDynamicResouce attached property.