How to change VisualState via ViewModel [duplicate]
I know this Question is similar to many. Anyway, I don't understand.
I have a several VisualStates (more than 2, thats why DataStateBehavior is not my solution). And I have ViewModel, which have enum property CurrentState. Every enum value represents to one state, also may be several enum values represents to one states, doesn't metter. I want VisualState changed when the CurrentState changed (thought, that immediately appears in my mind : Binding was created exactly for this case!)
Can I bind CurrentState with view VisualState (xaml-only solution), to get the behavior described above?
If yes开发者_Python百科, how can I do it?
If no, how should I use VisualStateManager.GoToState() method in my ViewModel?
I wanted to note a solution similar to @FasterSolutions', using built-in components of the Blend SDK.
Set a PropertyChangedTrigger
on the view-model's "CurrentState" property, and add a GoToStateAction
to change the visual state:
<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>
I wouldn't use VisualStateManager.GoToState in the ViewModel for a number of reasons, the biggest being you have to pass in the control whose visual state you're going to change. Passing UI controls up to your viewmodel goes against the whole MVVM approach.
My suggestion is to use (for Windows 8 Store) Winrt Behaviours or to use the Blend system.windows.interactivity.dll (for same functionality) to take a VisualState name from a viewmodel and update an object. The code would look something like this:
ViewModel:
public string State{
get{_stateName;}
set{_stateName=value;
RaisePropertyChanged("State");
}
View:
<Grid>
<I:Interaction.Behaviors>
<b:VisualStateSettingBehavior StateToSet="{Binding State}"/>
</i:Interaction.Behaviors>
</Grid>
Behavior:
public class VisualStateSettingBehavior:Behavior<Control>
{
StateToSet{
get{GetValue(StateProperty) as string;}
set{SetValue{StateProperty,value);
LoadState();}
}
private void LoadState()
{
VisualStateManager.GoToState(AssociatedObject,StateToSet,true);
}
}
What the behaviour is doing is connecting up to the control and allowing you, in a programmatic way, to extend its functionality. This approach allows you to keep the ViewModel separate from your View.
精彩评论