Переключение между представлениями в зависимости от состояния - PullRequest
3 голосов
/ 06 января 2012

Скажем, у меня есть приложение, которое отображает список друзей пользователя. Список друзей отображается в виде TabItem. Пользователь должен сначала войти на сервер, чтобы получить список друзей.

Я создал два пользовательских элемента управления: один для входа пользователя, другой для разблокировки. что-то в одиночку эта строка:

UnloggedView.xaml

<UserControl x:Class="UnloggedView" ...>
    <TextBlock ...>You need to <Hyperlink Command="{Binding LoginCmd}">
        Login</Hyperlink>too see your friends list</TextBlock>
</UserControl>

LoggedView.xaml:

<UserControl x:Class="LoggedView" ...>
    ...
    <ListView ItemSource={Binding Path=friends}">...
</UserControl>

Главное окно имеет следующий код:

....
<TabItem Header="Friends">
    <vw:UnloggedView />
</TabItem>

Я считаю, что все в соответствии с принципом MVVM. LoginCmd - это упрощенный вариант DelegateCommand (из призмы), реализованный во ViewModel. Оба Представления работают нормально, и, поскольку список заполняется (асинхронно), уведомления запускаются, и Представление обновляется. Я счастлив.

Итак, у меня есть два вопроса: Первый вопрос - как запустить окно LoginWindow (где пользователю предлагается ввести свои учетные данные? Сейчас я просто создаю LoginWindow (объект представления) и представляю его с помощью ShowDialog. похоже, что я нарушаю правила MVVM, напрямую манипулируя пользовательским интерфейсом из ViewModel.

Главный вопрос: после того, как я войду в систему с сервера, как правильно заменить содержимое TabItem на LoggedView. Согласно принципам MVVM, ViewModel не должна иметь знаний о внутренностях View. Я раскрываю свойство IsLogged во ViewModel (которое будет запускать уведомление PropertyChanged), но что мне следует связать с тем, чтобы все происходило? Я действительно не хочу, чтобы ViewModel манипулировал View.

Спасибо

Ответы [ 3 ]

9 голосов
/ 06 января 2012

Я вижу, что этот вопрос часто возникает и что-то написал о переключении между представлениями / пользовательскими элементами управления здесь . Обычно я использую ContentControl и выключаю ContentTemplate на основе DataTrigger, однако тот же принцип работает для переключения TabControl ItemTemplate

<DataTemplate x:Key="LoggedOutTemplate">
     <local:UnloggedView />
</DataTemplate> 

<DataTemplate x:Key="LoggedInTemplate">
     <local:LoggedView />
 </DataTemplate>

 <TabControl>
     <TabControl.Style>
         <Style TargetType="{x:Type TabControl}">
             <Setter Property="ItemTemplate" Value="{StaticResource LoggedOutTemplate}" />
             <Style.Triggers>
                 <DataTrigger Binding="{Binding IsLoggedIn}" Value="True">
                     <Setter Property="ItemTemplate" Value="{StaticResource LoggedInTemplate}" />
                 </DataTrigger>
             </Style.Triggers>
         </Style>
     </TabControl.Style>
 </TabControl>

Возможно, вам придется использовать ElementName или RelativeSource в привязке DataTrigger, чтобы найти свойство IsLoggedIn в вашем DataContext

Что касается запуска команды входа в систему из вида «Выйти», существует несколько способов сделать это.

Мой предпочтительный метод - использовать какую-то систему обмена сообщениями, такую ​​как Messenger от MVVM Light или EventAggregator от Microsoft Prism , и запускать какое-то сообщение ShowLoginDialog, когда кнопка нажмите, затем позвольте любому ViewModel позаботиться о том, чтобы отображалось диалоговое окно входа в систему, подпишитесь, чтобы получать эти сообщения и обрабатывать их.

Другой способ - просто использовать привязку RelativeSource, чтобы найти объект в дереве визуалов, который имеет LoginCommand в своем DataContext, и привязать к нему.

Примеры обоих можно посмотреть здесь

1 голос
/ 06 января 2012

Сначала я отвечу на второй вопрос ... Просто создайте Enum как SessonState

 enum SesionState
 {
      LoggedOut=0,
      LoggedIn
 }

После этого создайте в вашем ViewModel свойство для окна с именем SessionState и обновите это свойство требуемым значением при входе в систему и выходе из системы.

Xaml требуется для переключения видов

<Window>
        <Window.Resources>        
    <DataTemplate x:Key="LoggedOutView">
        <ViewLayer: LoggedOutView/>
    </DataTemplate>
    <DataTemplate x:Key="LoggedInView">
        <ViewLayer:LoggedInView/>
    </DataTemplate>
    <Style x:Key="mainContentControlStyle"
           TargetType="{x:Type ContentControl}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=SessionState}"
                         Value="0">
                <Setter Property="ContentTemplate" Value="{StaticResource ResourceKey=LoggedOutView}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=Mode}"
                         Value="1">
                <Setter Property="ContentTemplate" Value="{StaticResource ResourceKey=LoggedInView}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
    <Grid>
        <TabControl>
           <TabItem>
                        <ContentControl Grid.Row="0"
                    Content="{Binding}"
                    Style="{StaticResource ResourceKey=mainContentControlStyle}">  
           </TabItem>
        </TabControl>
    </Grid>
</Window>
0 голосов
/ 06 января 2012

для вашего первого вопроса: вы можете просто использовать ILogindialogservice из вашей модели представления. я использую после для диалогов и mvvm. его "юнит тест" способен и не ломается мввм.

EDIT. в вашей viewmodel у вас будет строка примерно такая:

var result = this.loginservice.ShowDialog("Login", loginvm);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...