views:

128

answers:

2

Hey all, I've got a scenario where I want to switch the visiblity of 4 different content controls. The visual states I have set opacity, and collapsed based on each given state (See code.) What I'd like to do is have the visual state bound to a property of my View Model of type Enum. I tried using DataStateBehavior, but it requires true/false, which doesn't work for me. So I tried DataStateSwitchBehavior, which seems to be totally broken for WPF4 from what I could tell. Is there a better way to be doing this? I'm really open to different approaches if need be, but I'd really like to keep this enum in the equation.

Edit:

The code shouldn't be too important, I just need to know if there's a well known solution to this problem.

<UserControl
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:Custom="http://schemas.microsoft.com/expression/2010/interactivity" 
         xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
         xmlns:ee="http://schemas.microsoft.com/expression/2010/effects" 
         xmlns:customBehaviors="clr-namespace:SEL.MfgTestDev.ESS.Behaviors"
         x:Class="SEL.MfgTestDev.ESS.View.PresenterControl" 
         mc:Ignorable="d" 
         d:DesignHeight="624" 
         d:DesignWidth="1104" 
         d:DataContext="{Binding ApplicationViewModel, Mode=OneWay, Source={StaticResource Locator}}">
<Grid>
    <Grid.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Layout/TerminalViewTemplate.xaml"/>
                <ResourceDictionary Source="Layout/DebugViewTemplate.xaml"/>
                <ResourceDictionary Source="Layout/ProgressViewTemplate.xaml"/>
                <ResourceDictionary Source="Layout/LoadoutViewTemplate.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Grid.Resources>
    <Custom:Interaction.Behaviors>
        <customBehaviors:DataStateSwitchBehavior Binding="{Binding ApplicationViewState}">
            <customBehaviors:DataStateSwitchCase State="LoadoutState" Value="Loadout"/>
        </customBehaviors:DataStateSwitchBehavior>
    </Custom:Interaction.Behaviors>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="ApplicationStates" ei:ExtendedVisualStateManager.UseFluidLayout="True">
            <VisualStateGroup.Transitions>
                <VisualTransition GeneratedDuration="0:0:1">
                    <VisualTransition.GeneratedEasingFunction>
                        <SineEase EasingMode="EaseInOut"/>
                    </VisualTransition.GeneratedEasingFunction>
                    <ei:ExtendedVisualStateManager.TransitionEffect>
                        <ee:SmoothSwirlGridTransitionEffect/>
                    </ei:ExtendedVisualStateManager.TransitionEffect>
                </VisualTransition>
            </VisualStateGroup.Transitions>
            <VisualState x:Name="LoadoutState">
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="LoadoutPage">
                        <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="LoadoutPage">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="ProgressState">
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="ProgressPage">
                        <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ProgressPage">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="DebugState">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="DebugPage">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                    </ObjectAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="DebugPage">
                        <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="TerminalState">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="TerminalPage">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                    </ObjectAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="TerminalPage">
                        <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <ContentControl x:Name="LoadoutPage" ContentTemplate="{StaticResource LoadoutViewTemplate}" Opacity="0" Content="{Binding}" Visibility="Collapsed"/>
    <ContentControl x:Name="ProgressPage" ContentTemplate="{StaticResource ProgressViewTemplate}" Opacity="0" Content="{Binding}" Visibility="Collapsed"/>
    <ContentControl x:Name="DebugPage" ContentTemplate="{StaticResource DebugViewTemplate}" Opacity="0" Content="{Binding}" Visibility="Collapsed"/>
    <ContentControl x:Name="TerminalPage" ContentTemplate="{StaticResource TerminalViewTemplate}" Opacity="0" Content="{Binding}" Visibility="Collapsed"/>
    <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding ApplicationViewState}">
        <TextBlock.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="Black" Offset="0"/>
                <GradientStop Color="White" Offset="1"/>
            </LinearGradientBrush>
        </TextBlock.Background>
    </TextBlock>
</Grid>

A: 

Use a valueconverter (class implementing IValueConverter) to convert from the enum to Visibility.

Wallstreet Programmer
That doesn't allow me to trigger storyboards tho.
Firoso
My answer was regarding your question how to databind the visibility of a control to an enum property in your viewmodel.
Wallstreet Programmer
However, the question was about settings a VisualState by evaluating a data bound enum. You didn't fully address the question.
Firoso
+1  A: 

You can do this easily by following the steps below:

  1. Create an event that will be raised when the enum property is changed
  2. Add a GotToStateAction (Behavior) for every value of the enum (define the value in the Conditions part) to change the Visual state. When the property is set the first time and every time the value changes the state will be set to the correct state.

More info on the GoToStateAction can be found here: http://blogs.msdn.com/b/expression/archive/2010/02/22/switching-visual-states-easily-using-gotostateaction.aspx

Wouter Janssens - Xelos bvba
I ended up doing this a whiel back and never responded to the question here, you summed it up nicely. However if you are using the MVVM pattern it's best to just use a property that implements INotifyPropertyChanged.
Firoso