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

时间:2018-01-16 21:17:45

标签: c# mvvm uwp mvvm-light uwp-xaml

在具有MVVM Light的UWP应用程序中,我试图将VisualStateGroup的当前状态绑定到ViewModel中的属性。我们的想法是根据应用程序逻辑通过更改视图模型中属性的值来更改当前状态。

几年前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中添加了更多代码,以便更好地澄清问题。

1 个答案:

答案 0 :(得分:1)

  

但是使用此代码,在执行构造函数之后,当前状态保持为null,并且进一步的赋值不起作用。它可能是使用DataTriggerBehavior或GoToStateAction。

由于我没有看到您的整个代码,我不确定您的其他代码块是否存在某些问题。但是检查上面的代码,您需要做一些更改。您需要将Interactivity:Interaction.Behaviors移出VisualStateGroup,如下所示:

<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,请确保您已为您的网页类分类了'DataContext'。

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

然后,根据我的测试,我发现在绑定值发生变化之前不会触发'DataTriggerBehavior'。我不知道这是否是默认行为,GitHub上存在同样的问题。

因此,您可以更改页面加载事件中的“VsmConnectionStatus”值,而不是在viewmodel的构造函数方法中执行此操作。

例如,

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()
    {}
}