将 VisualStateGroup 的当前状态绑定到 UWP MVVM 应用程序视图模型中的 属性

Binding the current state of a VisualStateGroup to a property in the view model in a UWP MVVM app

在带有 MVVM Light 的 UWP 应用程序中,我试图将 VisualStateGroup 的当前状态绑定到 ViewModel 中的 属性。思路是根据应用逻辑,通过改变view model中a属性的值来改变当前状态。

此问题已在 this question 几年前解决。我对 Olav(第二个答案)建议的方法很感兴趣,因为我的应用程序是 UWP 应用程序,所以不能直接遵循。

我的xaml来了:

<Page
    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" 
    xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
    x:Class="Smallrobots.Ev3RemoteController.Views.Settings"
    mc:Ignorable="d"

    DataContext="{Binding MainViewModel, Source={StaticResource Locator}}">

    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="ConnectionStatus">
                <Interactivity:Interaction.Behaviors>
                    <Core:DataTriggerBehavior Binding="{Binding VsmConnectionStatus}" 
                                              Value="{Binding VsmConnectionStatus}">
                        <Core:GoToStateAction StateName="{Binding VsmConnectionStatus}"/>
                    </Core:DataTriggerBehavior>
                </Interactivity:Interaction.Behaviors>
                <VisualState x:Name="Connected">
                    <VisualState.Setters>
                        <Setter Target="button.(Control.IsEnabled)" Value="False"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Button x:Name="button" Content="Connect"/>
    </Grid>
</Page>

MainViewModel:

public class MainViewModel : ViewModelBase
{
    private string vsmConnectionStatus = "";
    public string VsmConnectionStatus
    {
        get => vsmConnectionStatus;
        set
        {
            if (!vsmConnectionStatus.Equals(value))
            {
                vsmConnectionStatus = value;
                RaisePropertyChanged("VsmConnectionStatus");
            }
        }
    }

    public MainViewModel()
    {
        VsmConnectionStatus = "Connected";
    }
}

然而,对于这段代码,在执行构造函数后,当前状态保持 null,进一步的赋值无效。可能是 DataTriggerBehaviorGoToStateAction.

的使用

怎么了?非常感谢!

编辑: 我在 xaml 中添加了更多代码,以更好地阐明问题。

However with this code, after the constructor has been executed, the current state remains null and further assignments have no effect. It could be the use of the DataTriggerBehavior or of the GoToStateAction.

由于我没有看到你的全部代码,我不确定你的其他代码块是否有问题。但是检查上面的代码,您需要做一些更改。您需要将 Interactivity:Interaction.BehaviorsVisualStateGroup 中移出,如下所示:

<Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="ConnectionStatus">
            <VisualState x:Name="Connected">
                <VisualState.Setters>
                    <Setter Target="button.(Control.IsEnabled)" Value="False"/>
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="NotConnected">
                <VisualState.Setters>
                    <Setter Target="button.(Control.IsEnabled)" Value="True"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Interactivity:Interaction.Behaviors>
        <Core:DataTriggerBehavior Binding="{Binding VsmConnectionStatus}" 
                                      Value="{Binding VsmConnectionStatus}">
            <Core:GoToStateAction StateName="{Binding VsmConnectionStatus}"/>
        </Core:DataTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
    <Button Content="{Binding VsmConnectionStatus}" x:Name="button">
    </Button>
</Grid>

其次,如果您想使用 Binding,请确保您已经为您的页面 class 指定了 'DataContext'。

public MainPage()
{
    this.InitializeComponent();
    this.DataContext = new MainViewModel();
}

然后,根据我的测试,我发现'DataTriggerBehavior'只有在绑定值发生变化时才会被触发。我不知道这是否是默认行为,GitHub.

上也有同样的问题

因此,您可以在页面的加载事件中更改 'VsmConnectionStatus' 值,而不是在视图模型的构造方法中进行。

例如,

public MainPage()
{
    this.InitializeComponent();
    this.DataContext = new MainViewModel();
    this.Loaded += MainPage_Loaded;
}

private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    MainViewModel mvm = this.DataContext as MainViewModel;
    mvm.VsmConnectionStatus = "Connected";
}
public class MainViewModel : ViewModelBase
{
    private string vsmConnectionStatus = "";
    public string VsmConnectionStatus
    {
        get => vsmConnectionStatus;
        set
        {
            vsmConnectionStatus = value;
            RaisePropertyChanged("VsmConnectionStatus");
        }
    }

    public MainViewModel()
    {}
}