【问题标题】:UWP/VB.Net - Change Bound Button Color Dependent on VariableUWP/VB.Net - 根据变量更改绑定按钮颜色
【发布时间】:2017-02-02 09:36:09
【问题描述】:

我对 UWP 有点陌生。我花了两天时间寻找这个答案,但还没有找到答案。我知道我可能完全错误地处理了这个问题。感谢所有帮助!

我在我的 App.xaml 文件中创建了一个 SolidColorBrush StaticResource

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

我已将此画笔绑定到几个页面上几个按钮的背景属性。例如,我像这样绑定按钮:

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

效果很好,按钮背景是所需的红色。当我更改StaticResource 的颜色时,问题就出现了。按钮颜色不变。如果我在更改颜色后打开另一个页面,新页面上的按钮将根据需要变为绿色,但我无法在已打开的页面上获得按钮来更改颜色。

所以这就是场景。当用户'ClockedIn'时,绑定按钮需要为绿色,当用户下班时,绑定按钮需要变为红色,反之亦然。这是 App.xaml.vb 文件中的后端代码:

    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

当用户点击'ClockIn'按钮时,上面的代码被调用。我想我需要一个INotifyPropertyChanged 事件来让UI 知道colorClockStatus 属性已更改,因此需要重绘按钮,但我不知道如何使用StaticResource 来做到这一点。我也尝试过实现VisualStateManager,并创建两个SaticResources 之间的按钮开关(这似乎是一种更好的方法),但我不知道如何根据布尔值'ClockIn'设置触发器变量,然后全局实现管理器。

那么如何让 UI 根据布尔变量改变颜色?

谢谢!

更新

我一直在研究这个问题,并找到了一个使用StateTriggerBasehere 的示例。我修改了此代码以适用于布尔属性。以下是我改编的课程:

    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

然后,我不是只有一个StaticResource,而是两个:

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

然后我在我的 MainPage 中添加了一个 VisualStateManager 来测试它:

    <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>

当我打开程序,按钮是绿色的时候,我真的很兴奋! (默认情况下,按钮是红色的)但令我失望的是,当我打卡时,按钮并没有变回红色。我使用了调试器并且正在调用 SetActive(ClockedIn = _ClockedIn) 方法,但 UI 没有改变。我的绑定有问题吗?我需要调用一些方法来刷新 UI 吗?

【问题讨论】:

  • 如何改变VisualState的活跃度?在您发布的代码中,我没有找到像Current_SizeChanged 这样可以更改状态触发器的活动的方法。我也没有在你的代码中找到任何绑定。我不确定你的ClockedIn 是什么。是否要根据代码隐藏中设置的bool 值更改HamburgerButton.Background
  • 感谢@JayZuo-MSFT! ClockedIn 是我的 bool 属性,它在代码隐藏中设置,让应用程序知道用户是否打卡。上面的ClockedInTrigger 类继承了StateTriggerBase。通过这种继承,我希望&lt;local:ClockedInTrigger ClockedIn="False" /&gt;(绑定?)能够通过ClockedIn 属性集中的SetActive 方法获取属性更改。要回答最后一个问题,是的,我确实想根据 bool 值更改背景颜色,但我的最终目标是同时在多个页面上的多个控件上执行此操作

标签: vb.net xaml uwp uwp-xaml visualstatemanager


【解决方案1】:

为了实现你想要的,我认为你可以利用StateTriggerInvertBoolConverter,如下所示:

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

您也可以尝试使用WindowsStateTriggers,它是自定义视觉状态触发器的集合。您可以使用StateTriggerIsFalseStateTrigger 代替InvertBoolConverter。此外,请注意您需要为ClockedIn 属性实现INotifyPropertyChanged 才能使其工作。

【讨论】:

  • 谢谢@JayZuo-MSFT!!
猜你喜欢
  • 2016-07-04
  • 2015-10-14
  • 2018-03-16
  • 2011-02-02
  • 2018-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-14
相关资源
最近更新 更多