Home > Back-end >  Dynamic resource not updating ImageButton style in .NET MAUI
Dynamic resource not updating ImageButton style in .NET MAUI

Time:10-16

I defined two ContentPage level styles to be bound dynamically to an ImageButton. When the ImageButton click event is called, it is supposed to switch the ImageButton style, but this is not happening.

Below is the ContentPage content with the styles and the ImageButton definition:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SampleMobile.SamplePage"
             Title="">

    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="defaultStyle" TargetType="ImageButton">
                <Setter Property="BorderColor" Value="Grey"/>
                <Setter Property="BorderWidth" Value="2" />
            </Style>
            <Style x:Key="selectedStyle" TargetType="ImageButton">
                <Setter Property="BorderColor" Value="Blue"/>
                <Setter Property="BorderWidth" Value="5" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    <Grid RowDefinitions="50, 100, 5, 100, 5, 50, 100, 100, 100" ColumnDefinitions="*, *, *, *"
          Padding="25, 35, 25, 35" ColumnSpacing="5" RadioButtonGroup.GroupName="mobileNetworks">

        <Label Grid.Row="0" Grid.ColumnSpan="4"
            Text="Select Network"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />
        <ImageButton Source="first.png" Grid.Row="1" Grid.Column="0" HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{DynamicResource imageButtonStyle}"/>
        <ImageButton Source="second.png" Grid.Row="1" Grid.Column="1" BorderWidth="2" HeightRequest="50" WidthRequest="50" BorderColor="Grey" CornerRadius="10"/>
        <ImageButton Source="third.png" Grid.Row="1" Grid.Column="2" BorderWidth="2" HeightRequest="50" WidthRequest="50" BorderColor="Grey" CornerRadius="10"/>
        <ImageButton Source="fourth.png" Grid.Row="1" Grid.Column="3" BorderWidth="2" HeightRequest="50" WidthRequest="50" BorderColor="Grey" CornerRadius="10"/>

    </Grid>

</ContentPage>

Below is the code behind file where the first style is set, and the second style is set inside the click event handler:

public partial class SamplePage : ContentPage
{
    public SamplePage()
    {
        InitializeComponent();
        Resources["imageButtonStyle"] = Resources["defaultStyle"];
    }

    private void SelectImage(object sender, EventArgs e)
    {
        Resources["imageButtonStyle"] = Resources["selectedStyle"];
    
    }
}

I'm still trying to find what is wrong, and why it is not working as expected.

CodePudding user response:

You can use this.

First give the ImageButton a name like this x:Name="Image1"

I added 2 Buttons to change it and go back.

<ContentPage.Resources>
    <ResourceDictionary>
        <Style x:Key="defaultStyle" TargetType="ImageButton">
            <Setter Property="BorderColor" Value="Gray"/>
            <Setter Property="BorderWidth" Value="2" />
        </Style>
        <Style x:Key="selectedStyle" TargetType="ImageButton">
            <Setter Property="BorderColor" Value="Blue"/>
            <Setter Property="BorderWidth" Value="5" />
        </Style>
    </ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
    <Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
        <Label Text="Welcome to Xamarin.Forms!" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
    </Frame>
    <ImageButton x:Name="Image1"  Source="balzwart.png" Style="{DynamicResource defaultStyle}" />

    <Button Text="Change" Clicked="Button_Clicked" />
    <Button Text="Back" Clicked="Button_Clicked_1" />
</StackLayout>

and for the Button Click

 private void Button_Clicked(object sender, EventArgs e)
    {
        Image1.Style = (Style)Resources["selectedStyle"];
    }

    private void Button_Clicked_1(object sender, EventArgs e)
    {
        Image1.Style = (Style)Resources["defaultStyle"];
    }

enter image description here

CodePudding user response:

Instead of manipulating the styles at runtime, which is only a semi-good idea and should be done differently anyway, I recommend you do something like below instead using Visual States and only one Style for the ImageButton:

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

  <ContentPage.Resources>
    <ResourceDictionary>
      <Style x:Key="ImageButtonStyle" TargetType="ImageButton">
        <Setter Property="VisualStateManager.VisualStateGroups">
          <VisualStateGroupList>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Selected">
                <VisualState.Setters>
                  <Setter Property="BorderColor" Value="Blue" />
                </VisualState.Setters>
              </VisualState>
            </VisualStateGroup>
          </VisualStateGroupList>
        </Setter>
      </Style>
    </ResourceDictionary>
  </ContentPage.Resources>

  <Grid RowDefinitions="50, 100, 5, 100, 5, 50, 100, 100, 100" ColumnDefinitions="*, *, *, *"
        Padding="25, 35, 25, 35" ColumnSpacing="5" RadioButtonGroup.GroupName="mobileNetworks">

    <Label Grid.Row="0" Grid.ColumnSpan="4"
           Text="Select Network"
           VerticalOptions="Center" 
           HorizontalOptions="Center" />
    <ImageButton Source="first.png" Grid.Row="1" Grid.Column="0" BorderWidth="2"  HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{StaticResource ImageButtonStyle}"/>
    <ImageButton Source="second.png" Grid.Row="1" Grid.Column="1" BorderWidth="2" HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{StaticResource ImageButtonStyle}"/>
    <ImageButton Source="third.png" Grid.Row="1" Grid.Column="2" BorderWidth="2" HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{StaticResource ImageButtonStyle}"/>
    <ImageButton Source="fourth.png" Grid.Row="1" Grid.Column="3" BorderWidth="2" HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{StaticResource ImageButtonStyle}"/>

  </Grid>

</ContentPage>

In your Code Behind, you then can use the event handler to set the Visual State as follows:

private void SelectImage(object sender, EventArgs e)
{
    if (sender is ImageButton imageButton)
    {
        VisualStateManager.GoToState(imageButton, "Selected");
    }
}

This is just the minimal demonstration of how it can be done without manipulating a style in the resources. If you want to unselect the ImageButton again, you'll need to implement some logic and an Unselected Visual State.

  • Related