WPF - лучший способ реагировать на изменения в ViewModel на уровне страницы / окна - PullRequest
1 голос
/ 20 марта 2009

Я разрабатываю XBAP, и у меня есть простое требование.

DataContext всей главной страницы настроено на экземпляр моего UserViewModel. UserViewModel имеет DependencyProperty, называемый AuthenticationState, который является перечислением со значениями, такими как 'Authenticated', 'NotAutheticated' и 'AuthenticationFailed'

Теперь мне нужно реагировать на любые изменения этого значения, скрывая / отображая различные элементы на странице.

Какой (и где) лучший способ сделать это?

Ответы [ 5 ]

3 голосов
/ 20 марта 2009

Как вы упомянули, вы не можете использовать 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>
2 голосов
/ 20 марта 2009

Предпочтительным методом будет использование преобразователя с именем «AuthenticationStateToVisibilityConverter», который используется при привязке свойства Visibility элемента управления к свойству AuthenticationState контекста данных.

0 голосов
/ 20 марта 2009

удалось отсортировать его по стилям. Это боль, но это работает!

Полный источник ниже.

<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>
0 голосов
/ 20 марта 2009

На самом деле, лучший способ сделать это - выставить соответствующие свойства в вашей модели представления. Это делает вашу логику более централизованной и проще для тестирования. Кроме того, он работает лучше, чем конвертеры. В конце концов, это модель представления. Поэтому следует смоделировать вид. Если представлению необходимо свойство, чтобы указать, когда скрывать / отображать панель, добавьте такое свойство в модель представления.

0 голосов
/ 20 марта 2009

Лучший способ - использовать 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 окна, это должно работать!

...