WPF—在页面/窗口级别响应ViewModel更改的最佳方式
我正在开发XBAP,我有一个简单的要求 整个主页的WPF—在页面/窗口级别响应ViewModel更改的最佳方式,wpf,mvvm,triggers,viewmodel,Wpf,Mvvm,Triggers,Viewmodel,我正在开发XBAP,我有一个简单的要求 整个主页的DataContext被设置为myUserViewModel的一个实例。UserViewModel有一个名为AuthenticationState的dependencProperty,它是一个枚举,其值为“Authenticated”、“notauthenticated”和“AuthenticationFailed” 现在,我需要通过隐藏/显示页面上的各种元素来响应该值的任何更改 什么(以及在哪里)是最好的方法?最好的方法是使用数据触发器。比如说
DataContext
被设置为myUserViewModel
的一个实例。UserViewModel
有一个名为AuthenticationState
的dependencProperty
,它是一个枚举,其值为“Authenticated
”、“notauthenticated
”和“AuthenticationFailed
”
现在,我需要通过隐藏/显示页面上的各种元素来响应该值的任何更改
什么(以及在哪里)是最好的方法?最好的方法是使用数据触发器。比如说:
<Window.Triggers>
<DataTrigger Binding="{Binding AuthenticationState}" Value="NotAuthenticated">
<Setter TargetName="nameOfControl" Property="Visibility" Value="Collapsed" />
</DataTrigger>
...
<TextBox x:Name="nameOfControl" />
</Window.Triggers>
...
只要您的UserViewModel对象位于窗口的DataContext中,那么这应该可以工作 最好的方法是使用DataTrigger。比如说:
<Window.Triggers>
<DataTrigger Binding="{Binding AuthenticationState}" Value="NotAuthenticated">
<Setter TargetName="nameOfControl" Property="Visibility" Value="Collapsed" />
</DataTrigger>
...
<TextBox x:Name="nameOfControl" />
</Window.Triggers>
...
只要您的UserViewModel对象位于窗口的DataContext中,那么这应该可以工作 正如您所提到的,您不能直接在控件上使用DataTrigger。解决方法是在每个需要隐藏的控件上使用样式
<Grid>
<Rectangle Fill="Red" />
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding Test}" Value="true">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
正如您所提到的,您不能直接在控件上使用DataTrigger。解决方法是在每个需要隐藏的控件上使用样式
<Grid>
<Rectangle Fill="Red" />
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding Test}" Value="true">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
一个更好的方法是使用名为“AuthenticationStateToVisibilityConverter”的转换器,该转换器用于将控件的可见性属性绑定到数据上下文的AuthenticationState属性。一个更好的方法是使用名为“AuthenticationStateToVisibilityConverter”的转换器用于将控件的可见性属性绑定到数据上下文的AuthenticationState属性。实际上,最好的方法是从视图模型中公开适当的属性。这使您的逻辑更加集中,更易于测试。此外,它的性能优于转换器。毕竟,它是一个视图模型。因此,它应该为视图建模。如果视图需要属性来指示何时隐藏/显示面板,请将此类属性添加到视图模型中。实际上,最好的方法是从视图模型中显示适当的属性。这使您的逻辑更加集中,更易于测试。此外,它的性能优于转换器。毕竟,它是一个视图模型。因此,它应该为视图建模。如果视图需要属性来告诉它何时隐藏/显示面板,请将此类属性添加到视图模型。使用样式对其进行排序。这是一个痛苦,但它的工作
完整的资料来源如下
<Grid x:Name="contentGrid" Grid.Row="1">
<!--login-->
<controls:LoginControl>
<controls:LoginControl.Style>
<Style>
<Setter Property="Control.Opacity" Value="0"/>
<Setter Property="Control.IsHitTestVisible" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource UserViewModel},Path=UserAuthenticationState}"
Value="{x:Static model:AuthenticationState.NotAuthenticated}">
<Setter Property="Control.IsHitTestVisible" Value="True"/>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="1" Duration="0:0:2"
Storyboard.TargetProperty="Opacity"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="0" Duration="0:0:2"
Storyboard.TargetProperty="Opacity"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</controls:LoginControl.Style>
</controls:LoginControl>
<!--slider-->
<slider:PageSlider>
<Button>1</Button>
<Button>2</Button>
<Button>3</Button>
<slider:PageSlider.Style>
<Style>
<Setter Property="Control.Opacity" Value="0"/>
<Setter Property="Control.IsHitTestVisible" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource UserViewModel},Path=UserAuthenticationState}"
Value="{x:Static model:AuthenticationState.Authenticated}">
<Setter Property="Control.IsHitTestVisible" Value="True"/>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="1" Duration="0:0:2"
Storyboard.TargetProperty="Opacity"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="0" Duration="0:0:2"
Storyboard.TargetProperty="Opacity"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</slider:PageSlider.Style>
</slider:PageSlider>
</Grid>
1.
2.
3.
使用样式对其进行排序。这是一个痛苦,但它的工作
完整的资料来源如下
<Grid x:Name="contentGrid" Grid.Row="1">
<!--login-->
<controls:LoginControl>
<controls:LoginControl.Style>
<Style>
<Setter Property="Control.Opacity" Value="0"/>
<Setter Property="Control.IsHitTestVisible" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource UserViewModel},Path=UserAuthenticationState}"
Value="{x:Static model:AuthenticationState.NotAuthenticated}">
<Setter Property="Control.IsHitTestVisible" Value="True"/>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="1" Duration="0:0:2"
Storyboard.TargetProperty="Opacity"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="0" Duration="0:0:2"
Storyboard.TargetProperty="Opacity"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</controls:LoginControl.Style>
</controls:LoginControl>
<!--slider-->
<slider:PageSlider>
<Button>1</Button>
<Button>2</Button>
<Button>3</Button>
<slider:PageSlider.Style>
<Style>
<Setter Property="Control.Opacity" Value="0"/>
<Setter Property="Control.IsHitTestVisible" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource UserViewModel},Path=UserAuthenticationState}"
Value="{x:Static model:AuthenticationState.Authenticated}">
<Setter Property="Control.IsHitTestVisible" Value="True"/>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="1" Duration="0:0:2"
Storyboard.TargetProperty="Opacity"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="0" Duration="0:0:2"
Storyboard.TargetProperty="Opacity"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</slider:PageSlider.Style>
</slider:PageSlider>
</Grid>
1.
2.
3.