Switching to a visual state from code using the VisualStateManager - c#

A designer has given me a Silverlight child window that was designed in Expression Blend and uses a Visual State Manager to toggle between two modes. In short, there's an expand button on the child window that, when clicked, slides down another Grid control with detailed information.
This interaction happens entirely in the XAML. However, I need to enhance it so that if certain conditions are met - say if the user chooses some option, "Always show expanded details" - that when the child window is opened the expanded visual state will be in effect.
I thought this was as simple as calling:
VisualStateManager.GoToState(this, "VisualStateDetails", false);
But that is not working. What am I missing? (I apologize if I'm overlooking something obvious, I'm relatively new to Silverlight and not at all familiar with the Visual State Manager.)
Here is the XAML that has a bit removed for brevity.
<Grid x:Name="LayoutRoot" Margin="2" DataContext="{Binding ProjectNode, Mode=TwoWay}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="EditorWindowStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5">
<VisualTransition.GeneratedEasingFunction>
<CubicEase EasingMode="EaseInOut"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="VisualStateNormal"/>
<VisualState x:Name="VisualStateDetails">
<Storyboard>
<!-- snip -->
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<VisualStateManager.CustomVisualStateManager>
<ei:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<!-- snip -->
And here is a button that, when clicked, expands the details:
<Button ...>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction StateName="VisualStateDetails"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Thanks!

The issue appears to be that the Visual State Manager does not play nice in a Child window.
This blog entry described the problem and provides two workarounds. The first one (using the ExtendedVisualStateManager class) did the trick for me:
Using Visual State Manager with Silverlight Toolkit’s Child Windows control

Related

Settings "pop-up" WPF

I don't know how to name this, but the purpose is to when I click the right mouse button and then the left button right after (without opening the popup that usually opens with the right mouse button), it should popup this "settings menu" with an animation like this one:
or just a "size in". If it is not possible or its to complicate to open with the mouse buttons, it could be done with any key/combination from the keyboard.
Anyone has any idea how I could do this? Im using C# WPF and Blend.
I may have a partial answer for you. You can use a Radial Menu as the popup. There are many paid Radial Menu controls, but this (nugget package here) one seems open source and looks good (I haven't used it).
Regarding that loading animation, Expression Drawing might have a convenient Arc drawing to do that.
<ed:Arc x:Name="arc" Stretch="None" Height="64" Width="64" ArcThicknessUnit="Pixel" EndAngle="360" HorizontalAlignment="Stretch" Stroke="Red" StrokeThickness="5" StartAngle="0" />
And a simple storyboard can animate it.
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(ed:Arc.EndAngle)" Storyboard.TargetName="arc">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="360"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
Visual Studio Blend should help you do it very easily.

Adding a Top Navigation Bar in Windows 8 - Tutorial Issue

I am trying out a tutorial on WIndows 8. I need to add a Navigation Bar. The steps are given below;
The following is from the tutorial.
In Solution Explorer, double-click MainPage.xaml to open it.
In the Document Outline, select the "pageRoot" element.
In the Properties panel, click the Properties button () to show the Properties view.
Under Common in the Properties panel, find the TopAppBar property.
Click the New button next to TopAppBar. An AppBar control is added to the page.
In the Document Outline, expand the TopAppBar property.
Select the "photoPageButton" element, drag it onto the AppBar, and drop it.
Under Layout in the Properties panel, set the HorizontalAlignment property to Right ().
Press F5 to build and run the app. To test the app bar, right-click on the main page. The app bar opens at the top of the screen.
I Double-clicked on the MainPage.xaml, and then in the Document Outline i selected pageRoot. and in the properties Window expanded Common and i clicked on New next to TopAppBar.
It added several other Fields below it. Allow Drop, Background and Cache Mode are some of it. Then in the Document Outline i dragged the button to the AppBar under TopAddBar. Changed the HorizontalAlignment to Right, build and executed the application. But i don't see the button added to the top Navigation bar. What have i done wrong here ?
UPDATE
<Page.Resources>
<!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
<x:String x:Key="AppName">My Application</x:String>
</Page.Resources>
<common:LayoutAwarePage.TopAppBar>
<AppBar Background="#E5A41D1D" AllowDrop="True" BorderBrush="#E5C5A7A7" HorizontalAlignment="Right">
<Button Content="Next Page
" HorizontalAlignment="Right" VerticalAlignment="Stretch" Width="230" Height="70" Background="#FF12668D" FontFamily="Shruti" FontSize="36" Click="Button_Click_2"/>
</AppBar>
</common:LayoutAwarePage.TopAppBar>
<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Style="{StaticResource LayoutRootStyle}" Background="#FF282D40">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Back button and page title -->
<!-- Back button and page title -->
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="Welcome !!! " Style="{StaticResource PageHeaderTextStyle}" Foreground="#DE2374AC"/>
</Grid>
<VisualStateManager.VisualStateGroups>
<!-- Visual states reflect the application's view state -->
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<!-- The back button and title have different styles when snapped -->
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
You're following this tutorial here, correct? It looks like you've dragged the wrong button to your TopAppBar.
The button you should be dragging is named photoPageButton (its x:Name attribute). Instead, the button you've got in your TopAppBar doesn't have a name, and presents the text "Next Page".
Your XAML markup for the TopAppBar should look something like this after you've dragged the photoPageButton to the TopAppBar:
<common:LayoutAwarePage.TopAppBar>
<AppBar HorizontalAlignment="Right">
<Button x:Name="photoPageButton" Content="Go to photo page"/>
</AppBar>
</common:LayoutAwarePage.TopAppBar>
After you get a little farther in the tutorial and apply a style to the button, your markup for the TopAppBar will then look like this:
<common:LayoutAwarePage.TopAppBar>
<AppBar HorizontalAlignment="Right">
<Button x:Name="photoPageButton"
Click="photoPageButton_Click"
HorizontalAlignment="Right"
Style="{StaticResource PicturesAppBarButtonStyle}"/>
</AppBar>
</common:LayoutAwarePage.TopAppBar>
It's perfectly acceptable to have the other AppBar settings in there as well - Background, BorderBrush; these are harmless changes to the color - and AllowDrop defaults to true, I believe, so that's fine too.

Combobox style windows metro app

I'm developing a xaml/c# metro style app in windows 8. I'd like to emulate the Microsoft Calendar app comboBox Style (In the event details page). I mean, having that behavior of coloured box and border after selection. How can I do it using visual states?
There is no standard control for this, you have to create your own / extend the standard combobox
Something like this should work:
<Combobox.Template>
<ControlTemplate>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Unfocused"/> <!--leave the unfocused state empty if the control already looks "unfocused" -->
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="background" Storyboard.TargetProperty="Opacity" To="0.2" Duration="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="background" Background="Red" Opacity="0" />
<!--other stuff-->
</ControlTemplate>
</Combobox.Template>
The Combobox control automatically switches it's built-in states according to mouse/keyboard input like focused, pressed, mouse over etc. By switching a state the storyboard that was defined for the current state will be reversed and the storyboard that you have defined for the new state will be applied. You can review the available states here: http://msdn.microsoft.com/en-us/library/ms752094.aspx
(Using code-behind you can also implement your own states based on events and such, but this should be rarely needed.)

Custom Layout Aware Controls

I want to write a custom control and want it to have different Padding if the page is Portrait or Snapped. I noticed that pages inherit from LayoutAwarePage which creates support for the following view states:
FullScreenLandscape
Filled
FullScreenPortrait
Snapped
Do I need to add similar code to my new control (It inherits from Control). If not, why does LayoutAwarePage have to do this? Also, Can I just stick the following VisualStateManager into the ControlTemplate of my control and get it to respect the page layout or is this too easy.
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Padding">
<DiscreteObjectKeyFrame KeyTime="0" Value="1,2,3,4"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Padding">
<DiscreteObjectKeyFrame KeyTime="0" Value="5,6,7,8"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
EDIT : It looks like controls do not support these states by default and they have to be added. It also appears that ButtonBase does support these states because it uses them in its style.
If you look on the default "details" page within the windows 8 projects you'll find that it expects you to subscribe to the events on the page. You'll find the following within the flipview's ItemTemplate:
<FlipView.ItemTemplate>
<UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates">
<ScrollViewer x:Name="scrollViewer" Style="{StaticResource HorizontalScrollViewerStyle}"
<!-- "Child Controls Here" -->
<VisualStateManager.VisualStateGroups>
<!-- "Visual states manuiplating the child controls above" -->
</VisualStateManager.VisualStateGroups>
</ScrollViewer>
</UserControl>
</FlipView.ItemTemplate>
What I do with my user controls is to have them inherit LayoutAwarePage. Next place the content in a grid and move the VisualStateGroup inside this grid. Hope this helps, it works for me.

Checkbox triggers stackpanel expand/collapse animation

I have WP7 application with simple phone page.
I have check box
<CheckBox Content="Click me" Margin="0,2,0,0">
When I check the checkbox I want Stack panel below it to expand.
<StackPanel Height="0" x:Name="MyStackPanel">
<CheckBox Content="Condition"/>
</StackPanel>
Right now I tried this solution, but i receive exception that EventTrigger.RoutedEvent cannot be assign to Checkbox.Checked.
<CheckBox Content="Click Me" Margin="0,2,0,0">
<CheckBox.Triggers>
<EventTrigger RoutedEvent="CheckBox.Checked">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyStackPanel"
Storyboard.TargetProperty="Height"
To="100"
Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</CheckBox.Triggers>
</CheckBox>
Do you have any ideas what is the best approach to implement such animation?
Thanks
There is a control for what you require to do. You should be using the Expander control that iss part of the silverlight toolkit . There iS A good two part tutorial about working with this control here on WindowsPhoneGeek.
Basically, you use the expander control and implement your own custom controls for the header and the items.
try ToggleButton.Checked instead of CheckBox.Checked

Categories