locked
navigate to screen and activate state of a user component? RRS feed

  • Question

  • Hi There

    I have 2 screens. On screen1 I have a user control that contains a datagrid. I configured two states in my user control that shows either a blank grid or a grid with some data.

    So from screen 2, I want to click a button and have it navigate to screen 1, but show the user control in a particular state. Is this possible or am I barking up the wrong tree?

    Do I need to create a two states in my screen1, and have two different copies of my user control with the specific attributes set in each?

    and yes, I'm a sketchflow newbie of several days experience so don't assume I know too much :)   thanks for any help you can give me.

    cheers

    Andrew
    Thursday, March 4, 2010 4:48 AM

All replies

  • Hi Andrew,

    I've been trying to do a similar thing with a state that highlights a navigation item when entering a screen. I haven't had a whole lot of luck as yet but one solution I did find was to add an ActivateState behaviour to that screen that is triggered when you load the screen that you want your state change applied to.

    Apologies but I can't get to my Skecthflow files at the moment for the exact specifics of this. I'll append them to this post later.

    That said, this works for me only sometimes. I can't get it to work in all cases and am completely baffled as to why. I will try and keep you posted on what I learn or perhaps some other people in the forum will have some ideas.

    Best regards,

    Greg.
    Thursday, March 4, 2010 5:49 AM
  • Thanks Greg

    I've tried placing the grid directly into my screen1. From my screen2, I try to call ActivateStateAction with TargetScreen="Project.Screen1" and TargetState="ShowDataInGrid"


    It builds ok but falls over when testing. Do you know if you are even able to use ActivateStateAction in this manner - ie. targetting a state on another page ? Blend 3 seems a little buggy so I'm not sure if it's my lack of understanding or the app. Perhaps I'll try a clean project.

    thanks for the reply anyway, I would be interested in seeing more details as it would be a nicer solution.

    cheers

    Andrew
    Thursday, March 4, 2010 8:57 AM
  • What you want is going to be a little bit tricky, correct me if I am understanding your problem incorrectly:

    You have screen 1, with states A and B
    When you load screen 1 normally, you want state A
    When you load screen 1 from a link on screen 2, you want state B

    With the built in behaviors, there is no easy way to do that scenario.

    If you simply always want state B when screen 1 loads, you can attach an ActivateStateAction to something on screen 1, set the trigger event to "Loaded" and have it trigger the state.

    There may be another way to accomplish this however, if you make your datagrid into a component screen, and include it on screen 2, behaviors on screen 2 can change the state in the embedded component screen.

    For example:
    Select your datagrid, and right click it and pick "Make into component screen", unfortunately your visual states will stay on the containing screen, so you may have to re-create them
    Now create the button/objects you want to have activate the states, and right click them and pick "activate state -> componentname/statename"

    Hope that helps you come up with a way to accomplish your specific needs.  Please feel free to post more questions if this isn't clear.
    Thursday, March 4, 2010 3:02 PM
    Moderator
  • Hi Andrew,

    Ok so what you've done is basically what I was doing as well by using the ActivateStateAction.

    Something you might want to try is where you state TargetScreen="Project.Screen1". I read on a post somewhere about how this was used (sorry havn't been abe to find the post again).

    If my Skecthflow project is called "SampleProject.sln" then in this target I would actually enter:

    TargetScreen="SampleProjectScreens.Screen1"

    It seemed odd to do this but it worked for me so perhaps try that.

    Best regards,

    Greg
    Thursday, March 4, 2010 9:54 PM
  • Hi Chuck,

    I'm curious about where you state:

    "If you simply always want state B when screen 1 loads, you can attach an ActivateStateAction to something on screen 1, set the trigger event to "Loaded" and have it trigger the state."

    This makes perfect sense but I've found sketch flow doesn't work consistantly with this. In my project  have 3 screens and am trying to do just want you say as a technique to highlight nav buttons. This is my problem.

    Screen 1 initially loaded - state change works
    Screen 1 -> Screen 2 - state change doesn't work
    Screen 1 -> Screen 3 - state change doesn't work
    Screen 2 -> Screen 3 - state change works
    Screen 3 -> Screen 2 - state change works

    What baffles me is how the state change can work on the load from a screen other than screen 1 but doesn't work when loaded from screen 1.

    Any thoughts there?

    Best regards,

    Greg
    Thursday, March 4, 2010 9:57 PM
  • Hey Greg,

    Could you send me the project you are working on?  It is hard to determine exactly what is going on without seeing the xaml.  I'd be happy to see if I can sort out what is happening, or if there is another way to make it work correctly.

    First.Last@microsoft.com  (with my name)

    Friday, March 5, 2010 2:39 PM
    Moderator
  • Chuck thanks for your note. Actually my datagrid is already a component screen. I just left it out of my post to keep things simple. Your suggestion will work ok but can you explain how to switch back to screen1 after changing the component state? thanks Andrew
    Sunday, March 7, 2010 10:06 PM
  • Hi cyn3rgy, I'm happy to help, but I am having trouble following exactly what you want through all the messages above, could you describe what you have and what you want to have happen? 


    Monday, March 8, 2010 3:45 PM
    Moderator
  • Hi, I'm experiencing exactly the same problem. What we are basically tying to do is create a menubar in a component screen which has the button in a selected state for corresponding screens. On the homepage, the "home" button is lit, on the customers page, the "customers" button is lit and so on...

    To reproduce:

    1. Open sketchflow (4 RC)
    2. Create a new silverlight sketch project
    3. Draw 2 screens from the home screen in the sketchflow map
    4. On the homepage, create 3 buttons which we are going to use as a menu
    5. Group them into a component screen
    6. Add the component screen to all screens (drag component screen on the other screens in the map)
    7. Let the 3 buttons navigate to the 3 different screens (right-click on the button, navigate to...)
    8. In the component screen, make a "selected" state for every button
    9. On every screen, create an activatestateaction under the layoutroot, trigger onload, and activate the "selected" state on the corresponding button in the component screen.
    You will now see that when you are on the homepage, and click on the "customers" button for instance, it navigates correctly but the state of the customer-button does not change. But if you are on the customers page and you click on the "orders" button for instance, it navigates to the orders screen AND properly lits the orders button, as expected.

    Wednesday, May 12, 2010 1:50 PM
  • You may be hitting a known bug in V3 and early versions of V4.  The transitions between screens--for example fade or wipe---were blocking states from being applied on loading a screen.  In your SketchFlow map, try removing the transition style between these screens by right clicking on the connection between two screens and choosing Transition Style -> None.  Hopefully this will solve your problem.  If not, I'll be glad to take a look at your project if you can share.  kellycan@microsoft.com

    Barring any unforeseen regressions, this will be fixed in the final release of Blend 4. 

    Sorry for any inconvenience,
    Kelly

    • Proposed as answer by Kelly Cannon Wednesday, May 19, 2010 6:16 PM
    Wednesday, May 12, 2010 3:33 PM
  • This is actually a huge complaint from some users of blend I have come across. There is no simple way for them to navigate a prototype website or tab like structure to navigate to different screens and keep some 'navigation like bar' state of the buttons.

    So here is what I did: (Quick replica)

    Create three screens

    Create component screen with buttons (3)

    Inside component screen create 3 states (change background of button on these states)

    Link the component to all three screens

    Inside of the screen constructor, modify visual state of the component based on the screen your going too.

     

    Here is the breakdown:

     

    Screen 1 (XAML):

    <UserControl
    	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    	xmlns:local="clr-namespace:SilverlightPrototype1Screens"
    	mc:Ignorable="d"
    	x:Class="SilverlightPrototype1Screens.Screen_1"
    	Width="640" Height="480">
    
    	<Grid x:Name="LayoutRoot" Background="White">
    		<Grid.RowDefinitions>
    		<RowDefinition Height="Auto"></RowDefinition>	
    		<RowDefinition></RowDefinition>	
    		</Grid.RowDefinitions>
    		<local:NavBar x:Name="navBar" HorizontalAlignment="Left" Height="50" VerticalAlignment="Top" Width="100" d:IsPrototypingComposition="True"/>
    		<Grid Grid.Row="1" Background="#FFFD9999">
    			<TextBlock Text="Screen 1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="29.333"></TextBlock>
    		</Grid>
    	</Grid>
    </UserControl>
    Screen 1 (.CS):

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    
    namespace SilverlightPrototype1Screens
    {
    	public partial class Screen_1 : UserControl
    	{
    		public Screen_1()
    		{
    			// Required to initialize variables
    			InitializeComponent();
    
          VisualStateManager.GoToState(navBar, "One", true);			
    		}
    	}
    }

    Component (XAML):

    <UserControl
    	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    	xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:pi="http://schemas.microsoft.com/prototyping/2010/interactivity"
    	mc:Ignorable="d"
    	x:Class="SilverlightPrototype1Screens.NavBar">
    
    	<Grid x:Name="LayoutRoot" Background="White">
    		<VisualStateManager.VisualStateGroups>
    			<VisualStateGroup x:Name="VisualStateGroup">
    				<VisualState x:Name="One">
    					<Storyboard>
    						<ColorAnimation Duration="0" To="#FFFF7322" Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" Storyboard.TargetName="button" d:IsOptimized="True"/>
    					</Storyboard>
    				</VisualState>
    				<VisualState x:Name="Two">
    					<Storyboard>
    						<ColorAnimation Duration="0" To="#FFFF7322" Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" Storyboard.TargetName="button1" d:IsOptimized="True"/>
    					</Storyboard>
    				</VisualState>
    				<VisualState x:Name="Three">
    					<Storyboard>
    						<ColorAnimation Duration="0" To="#FFFF7322" Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" Storyboard.TargetName="button2" d:IsOptimized="True"/>
    					</Storyboard>
    				</VisualState>
    			</VisualStateGroup>
    		</VisualStateManager.VisualStateGroups>
    		<StackPanel Orientation="Horizontal">
    			<Button x:Name="button" Content="One">
    				<i:Interaction.Triggers>
    					<i:EventTrigger EventName="Click">
    						<pi:NavigateToScreenAction TargetScreen="SilverlightPrototype1Screens.Screen_1"/>
    					</i:EventTrigger>
    				</i:Interaction.Triggers>
    </Button>
    			<Button x:Name="button1" Content="Two">
    				<i:Interaction.Triggers>
    					<i:EventTrigger EventName="Click">
    						<pi:NavigateToScreenAction TargetScreen="SilverlightPrototype1Screens.Screen_2"/>
    					</i:EventTrigger>
    				</i:Interaction.Triggers>
    			</Button>
    			<Button x:Name="button2" Content="Three">
    				<i:Interaction.Triggers>
    					<i:EventTrigger EventName="Click">
    						<pi:NavigateToScreenAction TargetScreen="SilverlightPrototype1Screens.Screen_3"/>
    					</i:EventTrigger>
    				</i:Interaction.Triggers>
    			</Button>
    		</StackPanel>
    		
    	</Grid>
    </UserControl>

    Wednesday, May 12, 2010 3:40 PM
  • cyn3rgy:

    you should be able to use the same technique i outlined here to modify the state of your control when changing pages. make stats for the user control and change the visual state in the constructor of the screen.

    Wednesday, May 12, 2010 3:42 PM
  • "This is actually a huge complaint from some users of blend I have come across. There is no simple way for them to navigate a prototype website or tab like structure to navigate to different screens and keep some 'navigation like bar' state of the buttons."

    We've heard the complaints, and we've tried to address this in V4 with the NavigationMenuAction behavior.  If you apply this behavior to a component screen, you can specify an "active" state and an "inactivate" state triggered by what screen the component is displayed within.  So you could, for example, have a radio button be selected when the component is on Screen 1, but not selected when the component is on any other screen. 

    If you haven't had a chance to check it out, please do and give us any feedback.

    Thanks,
    Kelly

    Wednesday, May 12, 2010 4:16 PM
  • Thanks Kelly, looks like a nice feature for Blend 4!
    Wednesday, May 12, 2010 6:12 PM
  • Hi,

    Thanks Kelly, the problem was indeed the transitions that blocked the activatestateaction. I tried the NavigationMenuAction, but I could not get it to work. Couldn't find any documentation on how to use it either. Does this action navigate to the screen for you or only changes the state? Does it have to be in the layoutroot, at the load event or on the click event of a button?

    Cheers,

     

    Stefan

    Wednesday, May 19, 2010 8:55 AM
  • Hi Stefan,

    The NavigationMenuAction should be on a component screen that is instantiated into your other screens and it does not perform navigation for you.  It simply activates a particular state when the component screen is instantiated within the "TargetScreen."  We'll have documentation out soon, but in the meantime here's what I'd call a very basic example of how you could use this.

    Let's say you have two navigation screens, Screen 1 and Screen 2.  You'd like to have a navigation menu that allows you to navigate between the screens.  For simplicity sake, we'll say you'd like the navigation menu to contain two radio buttons - one labelled Screen 1 and one labelled Screen 2.

    First, create a component screen and instantiate it (by dragging and dropping) into Screen 1 and Screen 2.  Draw the two radio buttons.  Add "NavigateToScreen" behaviors so that clicking on the Screen 1 radio button navigates to Screen 1 and clicking on the Screen 2 radio button navigates to Screen 2.  You'll also need to add a NavigationMenuAction to each button.  For the first NavigationMenuAction, set the TargetObject to be the Screen 1 radio button.  Set the TargetScreen to be Screen 1.  Set the Active State to be Checked and the inactive state to be Unchecked.  Repeat with the appropriate modification (Scren 2 radio button and TargetScreen to be Screen 2) for the second NavigationMenuAction. 

    Now, when you run the project, clicking on Screen 1 should a) navigate to Screen 1 and b) show the Screen 1 radio button as checked and clicking on Screen 2 sholuld a) navigate to Screen 2 and b) show the Screen 2 radio button as checked.

    Note that this is just a common example.  You could also have actual visual states defined and have those triggered sa well. 

    Hope that helps.  If you have any specific questions, just let me know.

    Thanks, Kelly

    Wednesday, May 19, 2010 6:16 PM
  • Hi Kelly,

     

    Thanks for the walk-through! The docs could definitely use some work... It seems this is a very common need, and I also went down the "ActivateState" path and encountered erratic behavior. So I stumbled across this thread and tried NavigationMenuAction with a tiny bit of luck. My problem was that I didn't want to specify an "Inactive State", and when I did, the system choked.

    I created a control which has 6 main menu sections, which, when clicked, each shows a visual state with the corresponding sub-menu items. That is, clicking a main menu item doesn't take you to a new screen; only activates a specific state.

    I was attempting to set up each screen to activate the visual state which shows the main menu item selected, it's sub menu items displayed, and it's specific page menu item selected. There's no use to create an "Inactive State" and trying to do so caused conflicts and errors.

     

    Tuesday, December 28, 2010 8:22 PM