Как изменить VisualState через ViewModel

Я знаю, что этот вопрос похож на многих. Во всяком случае, я не понимаю.

У меня есть несколько VisualStates (более 2, поэтому DataStateBehavior не является моим решением). И у меня есть ViewModel, которые имеют свойство enum CurrentState. Каждое значение перечисления представляет одно состояние, также может быть несколько значений перечисления представляет одно состояние, не имеет значения. Я хочу, чтобы VisualState изменялся при изменении CurrentState (я подумал, что это сразу же приходит мне в голову: привязка была создана именно для этого случая!)

Могу ли я связать CurrentState с представлением VisualState (решение только для xaml), чтобы получить поведение, описанное выше?

Если да, как я могу это сделать?

Если нет, как я должен использовать метод VisualStateManager.GoToState() в моей ViewModel?

2 ответа

Решение

Я бы не стал использовать VisualStateManager.GoToState в ViewModel по ряду причин, самая большая из которых - передать элемент управления, визуальное состояние которого вы собираетесь изменить. Передача управления пользовательским интерфейсом до вашей модели представления противоречит всему подходу MVVM.

Я предлагаю использовать (для Windows 8 Store) Winrt Behaviors или использовать Blend system.windows.interactivity.dll (для той же функциональности), чтобы взять имя VisualState из viewmodel и обновить объект. Код будет выглядеть примерно так:

ViewModel:

public string State{
    get{_stateName;}
    set{_stateName=value;
        RaisePropertyChanged("State");
}

Посмотреть:

<Grid>
    <I:Interaction.Behaviors>
        <b:VisualStateSettingBehavior StateToSet="{Binding State}"/>
    </i:Interaction.Behaviors>
</Grid>

Поведение:

public class VisualStateSettingBehavior:Behavior<Control>
{

    StateToSet{
               get{GetValue(StateProperty) as string;}
               set{SetValue{StateProperty,value);
                    LoadState();}
}
private void LoadState()
{
VisualStateManager.GoToState(AssociatedObject,StateToSet,true);
}
}

Поведение выполняет подключение к элементу управления и позволяет программным способом расширить его функциональные возможности. Этот подход позволяет вам отделить ViewModel от вашего View.

Я хотел отметить решение, похожее на @FasterSolutions', использующее встроенные компоненты Blend SDK.

Установить PropertyChangedTrigger в свойстве "CurrentState" модели представления и добавьте GoToStateAction изменить визуальное состояние:

<i:Interaction.Triggers
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Inte‌​ractivity"  
    xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microso‌ft.Expression.Interactions">
    <ei:PropertyChangedTrigger Binding="{Binding CurrentState}">
        <ei:GoToStateAction StateName="{Binding CurrentState}" />
    </ei:PropertyChangedTrigger>
</i:Interaction.Triggers>
Другие вопросы по тегам