WPF—在页面/窗口级别响应ViewModel更改的最佳方式

WPF—在页面/窗口级别响应ViewModel更改的最佳方式,wpf,mvvm,triggers,viewmodel,Wpf,Mvvm,Triggers,Viewmodel,我正在开发XBAP,我有一个简单的要求 整个主页的DataContext被设置为myUserViewModel的一个实例。UserViewModel有一个名为AuthenticationState的dependencProperty,它是一个枚举,其值为“Authenticated”、“notauthenticated”和“AuthenticationFailed” 现在,我需要通过隐藏/显示页面上的各种元素来响应该值的任何更改 什么(以及在哪里)是最好的方法?最好的方法是使用数据触发器。比如说

我正在开发XBAP,我有一个简单的要求

整个主页的
DataContext
被设置为my
UserViewModel
的一个实例。
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.