Как изменить 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.Interactivity"
xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions">
<ei:PropertyChangedTrigger Binding="{Binding CurrentState}">
<ei:GoToStateAction StateName="{Binding CurrentState}" />
</ei:PropertyChangedTrigger>
</i:Interaction.Triggers>