Coaders Coaders - 4 years ago 145
Vb.net Question

UWP/VB.Net - Change Bound Button Color Dependent on Variable

I'm a little new to UWP. I've spent two days looking for this answer and haven't come across the answer yet. I know I could be approaching this completely wrong. All help is appreciated!

I have a

SolidColorBrush
StaticResource
I've created in my App.xaml file:

<Application.Resources>
<SolidColorBrush x:Key="colorClockStatus" Color="#cae0d5" />
</Application.Resources>`


I've bound this brush to the Background property of a few buttons on a few pages. For example, I bound the buttons it like this:

<Button Background="{StaticResource colorClockStatus}"/>


That works great, the button backgrounds are the desired red. The problem comes in when I change the color of the
StaticResource
. The button color doesn't change. If I open another page after the color change, the buttons on the new page will be green as desired, but I can't get a button on an already opened page to change color.

So here's the scenario. When the user is 'ClockedIn', the bound buttons need to be green, and when the user clocks out, the bound buttons need to turn red and vise versa. Here's the backend code in the App.xaml.vb file:

Public Shared ClockedIn As Boolean = False

Public Shared Sub SetClockedStatus(ByVal bClockedIn As Boolean)
ClockedIn = bClockedIn
With Application.Current
If bClockedIn Then
.Resources("colorClockStatus") = Color.FromArgb(255, 202, 224, 213) 'Green
Else
.Resources("colorClockStatus") = Color.FromArgb(255, 227, 184, 179) 'Red
End If
End With
End Sub


When the user taps the 'ClockIn' button, the above code is called. I think I need a
INotifyPropertyChanged
event to let the UI know the
colorClockStatus
property changed and therefore needs to redraw the buttons, but I don't know how to do this with a
StaticResource
. I've also have tried implementing a
VisualStateManager
, and create two
SaticResources
the button switches between (which seems like a better way), but I couldn't figure out how to set the trigger dependent on the Boolean 'ClockIn' variable, and then to implement the manager globally.

So how can I get the UI to change colors dependent on a Boolean variable?

Thank you!

UPDATE

I've been working on this some more and found an example using a
StateTriggerBase
class here. I adapted this code to work for a Boolean property. Below is my adapted class:

Public Class ClockedInTrigger
Inherits StateTriggerBase
Private _ClockedIn As Boolean = False

Public Property ClockedIn As Boolean
Get
Return _ClockedIn
End Get
Set
If Not Value.Equals(_ClockedIn) Then
_ClockedIn = _ClockedIn
SetActive(ClockedIn = _ClockedIn)
End If
End Set
End Property
End Class


Then, instead of having just one
StaticResource
, I made two:

<Application.Resources>
<SolidColorBrush x:Key="colorClockInLight" Color="#cae0d5" />
<SolidColorBrush x:Key="colorClockOutLight" Color="#e3b8b3" />
</Application.Resources>


Then I added a
VisualStateManager
to my MainPage to test it:

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ClockInStates">
<VisualState x:Name="vsClockedOut">
<VisualState.StateTriggers>
<local:ClockedInTrigger ClockedIn="False" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="HamburgerButton.Background" Value="{StaticResource colorClockOutLight}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="vsClockedIn">
<VisualState.StateTriggers>
<local:ClockedInTrigger ClockedIn="True" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="HamburgerButton.Background" Value="{StaticResource colorClockInLight}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>


I was really excited when I opened the program and the button was green! (By default, the button is red) But to my disappointment, the button did not turn back red when I clocked out. I used the debugger and the
SetActive(ClockedIn = _ClockedIn)
method is being called, but the UI doesn't change. Do I have something wrong with my binding? Is there some method I need to call to refresh the UI?

Answer Source

To achieve what you want, I think you can just take advantage of StateTrigger with a InvertBoolConverter like following:

XAML:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="ClockInStates">
        <VisualState x:Name="vsClockedOut">
            <VisualState.StateTriggers>
                <StateTrigger IsActive="{x:Bind ClockedIn, Converter={StaticResource InvertBoolConverter}, Mode=OneWay}" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="HamburgerButton.Background" Value="{StaticResource colorClockOutLight}" />
            </VisualState.Setters>
        </VisualState>
        <VisualState x:Name="vsClockedIn">
            <VisualState.StateTriggers>
                <StateTrigger IsActive="{x:Bind ClockedIn, Mode=OneWay}" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="HamburgerButton.Background" Value="{StaticResource colorClockInLight}" />
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

InvertBoolConverter:

Public Class InvertBoolConverter
    Implements IValueConverter

    Public Function Convert(value As Object, targetType As Type, parameter As Object, language As String) As Object Implements IValueConverter.Convert
        Dim boolValue = CBool(value)
        Return Not boolValue
    End Function

    Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, language As String) As Object Implements IValueConverter.ConvertBack
        Dim boolValue = CBool(value)
        Return Not boolValue
    End Function
End Class

Also you can try with WindowsStateTriggers which is a collection of custom visual state triggers. You can use StateTrigger and IsFalseStateTrigger instead of InvertBoolConverter. Besides, please note you need to implement INotifyPropertyChanged for ClockedIn property to make it work.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download