Home > Blockchain >  WPF STYLES - button with connected boolean variable changing background color
WPF STYLES - button with connected boolean variable changing background color

Time:12-06

I would like to achieve such configuration: button style in my WPF app - I have a process/windows service with hundreds of BOOL variables which I need to change a state from my WPF app/UI. Those variables can be controlled also by other apps.

So I have created a model/class in my WPFapp which is querying those variables and updating my internal variables states based on data. This is working fine.

I have such WORKING objects in my WPF View (for test)

<Button Width="30" Height="30">
    <Button.Resources>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Gray" />

            <Style.Triggers>
                <DataTrigger Binding="{Binding LifeBitVariable}" Value="True">
                    <Setter Property="Background" Value="Green" />
                </DataTrigger>

                <DataTrigger Binding="{Binding LifeBitVariable}" Value="False">
                    <Setter Property="Background" Value="Red" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Resources>
</Button>

And this in my VM:

public bool LifeBitVariable
{
    get => communication.LifeBitVariable;
    set 
    { 
        communication.LifeBitVariable = value; 
        NotifyPropertyChanged();
    }
}

How to change this to the style? I would like to have a button style and in my View call this style and just connect a variable from my ViewModel (each button will have different variable connected - this button style will be used in multiple View with multiple variables from ViewModel)

P.S. I would like to have this style in Resource Dictionary call later in APP.xaml and View by Style="{StaticResource MyStyle}".

CodePudding user response:

Ok, I found some guidance at this topic CLICK

So my final solution looks like this:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Style x:Key="MyButton"
       TargetType="Button">

    <Setter Property="Width"
            Value="100"/>
    <Setter Property="Height"
            Value="30"/>
    <Setter Property="Background"
            Value="#FFDECFCF" />

    <Style.Triggers>

        <DataTrigger Binding="{Binding}" Value="True">
            <Setter Property="Background" Value="Green"/>
        </DataTrigger>

        <DataTrigger Binding="{Binding}" Value="False">
            <Setter Property="Background" Value="Red"/>
        </DataTrigger>

    </Style.Triggers>
</Style>

and In my View:

<Button Style="{StaticResource MyButton}"
            DataContext="{Binding LifeBitVariable}" />

Everything is working as I was expecting! :)

CodePudding user response:

You can achieve this in multiple ways, here are two I can think of at the moment:

Option 1: Use a style Button within a DataTemplate (applicable if you have the items in a collection)

<ItemsControl ItemsSource="{Binding ConfigurationItems}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Width="30" Height="30">
                <Button.Resources>
                    <Style TargetType="Button">
                        <Setter Property="Background" Value="Gray" />

                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsActive}" Value="True">
                                <Setter Property="Background" Value="Green" />
                            </DataTrigger>

                            <DataTrigger Binding="{Binding IsActive}" Value="False">
                                <Setter Property="Background" Value="Red" />
                            </DataTrigger>
                        </Style.Triggers>

                    </Style>
                </Button.Resources>
            </Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Option 2: A custom control that inherits from Button

ConfigurationButton.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ConfigButtons;

public class ConfigurationButton : Button
{
    public static readonly DependencyProperty IsActiveProperty =
        DependencyProperty.Register(
          name: nameof(IsActive),
          propertyType: typeof(bool),
          ownerType: typeof(ConfigurationButton), 
          new FrameworkPropertyMetadata(defaultValue: false, propertyChangedCallback: IsActivePropertyChangedCallback));

    public bool IsActive
    {
        get => (bool)GetValue(IsActiveProperty);
        set => SetValue(IsActiveProperty, value);
    }
}

Usage:

App.xaml

<Style TargetType="local:ConfigurationButton" x:Key="MyConfigButton">
    <Setter Property="Background" Value="Gray" />

    <Style.Triggers>
        <DataTrigger Binding="{Binding IsActive}" Value="True">
            <Setter Property="Background" Value="Green" />
        </DataTrigger>

        <DataTrigger Binding="{Binding IsActive}" Value="False">
            <Setter Property="Background" Value="Red" />
        </DataTrigger>
    </Style.Triggers>

</Style>

MainWindow.xaml

<Window
    x:Class="ConfigButtons.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:ConfigButtons"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <WrapPanel>
        
        <!--This button will be RED-->
        <local:ConfigurationButton Content="OFF" Style="{StaticResource MyConfigButton}" />
        
        <!--And this one GREEN-->
        <local:ConfigurationButton Content="ON" IsActive="True" Style="{StaticResource MyConfigButton}" />
        
    </WrapPanel>
</Window>

I'm sure there are more ways to do this, I'm curious to see other answers.

  • Related