3

I have a UserControl with that XAML:

<StackPanel>
    <Label HorizontalContentAlignment="Center">
        <Rectangle Name="iconContainer" Height="120" Width="120" Fill="#FF045189">
            <Rectangle.OpacityMask>
                <VisualBrush Visual="{DynamicResource appbar_disconnect}"/>
            </Rectangle.OpacityMask>
        </Rectangle>
    </Label>
    <TextBlock Name="tBlockPortStatus" Foreground="#FF7C7676" FontWeight="Bold" FontSize="15" Margin="3" TextAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap">PORT STATUS (Testing wrapping text abilities for this control)</TextBlock>
</StackPanel>

I need to change the icon(named appbar_disconnect) and use another DynamicResource (ex. appbar_connect) using Code Behind or MVVM. How can I achieve this? Regards

SamTh3D3v
  • 9,854
  • 3
  • 31
  • 47
Dariel Nunez
  • 45
  • 1
  • 8
  • Change the icon based on what? – SamTh3D3v Feb 21 '18 at 01:27
  • Based on certain event trigger. But my question is how can I change this DynamicResource on runtime in order to use other icon. This UserControl will be showing the app state to the user, using icons and status messages. – Dariel Nunez Feb 21 '18 at 01:36

1 Answers1

2

Your case looks like it would be better handled using a Trigger than a DynamicResource, but if you insisted on using DynamicResource, you basically need to define your states' icons/images as resources in the App.xaml file:

 <Application.Resources>
    <Image Source="Icons/disconnect.png" x:Key="AppbarDisconnect"/>
    <Image Source="Icons/connect.png" x:Key="AppbarConnect"/>
    <Image Source="Icons/undefined.png" x:Key="AppbarStatus"/>
</Application.Resources>

Assuming your UserControl looks like that:

<StackPanel>
    <Label HorizontalContentAlignment="Center">
        <Rectangle Name="IconContainer" Height="120" Width="120" Fill="#FF045189">
            <Rectangle.OpacityMask>
                <VisualBrush Visual="{DynamicResource AppbarStatus}"/>
            </Rectangle.OpacityMask>
        </Rectangle>
    </Label>
    <TextBlock Name="TBlockPortStatus" Foreground="#FF7C7676" FontWeight="Bold" FontSize="15" Margin="3" TextAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap">PORT STATUS (Testing wrapping text abilities for this control)</TextBlock>
</StackPanel>

You could update the AppbarStatus resource on a specific event (from the code behind or from the viewmodel) like so:

Application.Current.Resources["AppbarStatus"] = Application.Current.Resources["AppbarDisconnect"];

Update

In case you want to use a DataTrigger, just add a property to hold the connection-status to your user control:

private bool _connetionStatus;
    public bool ConnectionStatus
    {
        get { return _connetionStatus; }
        set
        {
            if (value == _connetionStatus) return;
            _connetionStatus = value;
            OnPropertyChanged();
        }
    }

The DataTrigger should be self explanatory:

 <StackPanel>
        <Label HorizontalContentAlignment="Center">
            <Rectangle Name="IconContainer" Height="120" Width="120" Fill="#FF045189">
                <Rectangle.Style>
                    <Style TargetType="Rectangle">
                        <Setter Property="OpacityMask">
                            <Setter.Value>
                                <VisualBrush Visual="{DynamicResource AppbarDisconnect}"/>
                            </Setter.Value>
                        </Setter>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding ConnectionStatus}" Value="true">
                                <Setter Property="OpacityMask">
                                    <Setter.Value>
                                        <VisualBrush Visual="{DynamicResource AppbarConnect}"/>
                                    </Setter.Value>
                                </Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </Rectangle.Style>

            </Rectangle>
        </Label>
        <TextBlock Name="TBlockPortStatus" Foreground="#FF7C7676" FontWeight="Bold" FontSize="15" Margin="3" TextAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap">PORT STATUS (Testing wrapping text abilities for this control)</TextBlock>
    </StackPanel>
SamTh3D3v
  • 9,854
  • 3
  • 31
  • 47
  • I'm new on WPF, so I would like to know how can I use triggers in that specific problematic. – Dariel Nunez Feb 21 '18 at 16:52
  • Awesome!!! Thanks!! but this code will change the icons to all my tiles, ok let me be more clear, I'm building and application to control comports and giving to the user an idea whats is happening in real time, so I'll have more than one of those UC showing different COMPORT status at the same time. I need to be able to change the icon of each UC depending of the current port status. – Dariel Nunez Feb 21 '18 at 17:10
  • As i said a `DataTrigger` or a simple `Trigger` looks more appropriate for such scenario, just attach a property (an enum or a bool) to each UC, and update the `VisualBrush` using the trigger accordingly. Check out my updated answer. – SamTh3D3v Feb 22 '18 at 10:27
  • 1
    Awesome!!! following that idea I can also add more status (Ex. Reading, Writing, Error Communicating with Port, Printing, etc etc etc) Thanks! – Dariel Nunez Feb 22 '18 at 17:30
  • `.Resources` is not exclusive to `Application` so you can set it in YourPage.xaml as `ContentPage.Resources` for example and use practically the same code as in this answer (before update). – s3c Aug 26 '21 at 07:15