在具有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
,并且进一步的分配无效。可以使用DataTriggerBehavior
或GoToStateAction
。
有什么问题?非常感谢!
编辑:我在xaml中添加了更多代码,以便更好地澄清问题。
答案 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()
{}
}