locked
How to read TargetScreen property RRS feed

  • Question

  • I simply trying to get (read) the TargetScreen property in Sketchflow via a MessageBox.  When invoked, nothing happens - not even an uncaught exception.

     

    Here is my sample:

    <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="TestProjectScreens.Screen_1"
     Width="800" Height="600">

     <Grid x:Name="LayoutRoot" Background="White">
      <Button Content="Button" Margin="325,0,0,267" Style="{StaticResource Button-Sketch}" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="75" Click="Button_Click">
       <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
         <pi:NavigateToScreenAction x:Name="NavToScreenButton" TargetScreen="TestProjectScreens.Screen_2"/>
        </i:EventTrigger>
       </i:Interaction.Triggers>
      </Button>
     </Grid>
    </UserControl>

     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 TestProjectScreens
    {
     public partial class Screen_1 : UserControl
     {
      public Screen_1()
      {
       // Required to initialize variables
       InitializeComponent();
      }

      private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
      {
       MessageBox.Show(NavToScreenButton.TargetScreen);
       // TODO: Add event handler implementation here.
      }

     

    Monday, May 23, 2011 5:56 PM

Answers

  • I don't think you can find triggers/actions by name in that way, this code finds the first NavigateToScreenAction attached to a control and shows the TargetScreen property in a message box:

    using System;
    using System.Linq;
    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();
    		}
    
    		private void Go(object sender, System.Windows.RoutedEventArgs e)
    		{
    			
    			var triggers = System.Windows.Interactivity.Interaction.GetTriggers(this.Button);
    
    			foreach (var trigger in triggers)
    			{
    				var navAction = trigger.Actions.OfType<Microsoft.Expression.Prototyping.Behavior.NavigateToScreenAction>().FirstOrDefault();
    				if (navAction != null)
    				{
    					MessageBox.Show(navAction.TargetScreen);
    				}
    			}
    		}
    	}
    }
    

    Monday, May 23, 2011 6:41 PM
    Moderator
  • I was able to figure it out.  I of course research various issues until I found the solution that meets my specific requirement.  You will see it is a derivative of your original response.

     

    One benefit is now I can dynamically at run time set the TargetScreen property allowing NavigateToScreen action to be dynamically routed (with additional code but he fundemental is here).  I have also since found out how to dynamically read the selected value in my combo box (that is populated via a data collection) and with the code below route to the proper screen.

    Misc. Info:

    1.  MUST give the Object (Button, etc.) a name and set a default TargetScreen  in your XAML (can be done easily with the Blend UI).  I Called it LogonButton for my example

    2. MUST define System.Linq assemble/reference (thanks chuck)

     

    Example:

     System.Windows.Interactivity.TriggerCollection triggerCollection = Interaction.GetTriggers(this.LogonButton);
      
       
    foreach (System.Windows.Interactivity.TriggerBase trigger in triggerCollection)
       {
        
       
      var navAction =  (Microsoft.Expression.Prototyping.Behavior.NavigateToScreenAction) trigger.Actions.FirstOrDefault();
      
        MessageBox.Show("DEFAULT OR PRIORLY SET TargetScreen"+ navAction.TargetScreen);

     

    //Can at run time set TargetScreen property which will route to alternate page.


        navAction.TargetScreen = "name_space.name_of_page";
        
        MessageBox.Show("UPDATED TargetScreen" + navAction.TargetScreen);

        
       }

     



    • Marked as answer by stanglx Friday, May 27, 2011 2:57 PM
    Friday, May 27, 2011 2:56 PM

All replies

  • I don't think you can find triggers/actions by name in that way, this code finds the first NavigateToScreenAction attached to a control and shows the TargetScreen property in a message box:

    using System;
    using System.Linq;
    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();
    		}
    
    		private void Go(object sender, System.Windows.RoutedEventArgs e)
    		{
    			
    			var triggers = System.Windows.Interactivity.Interaction.GetTriggers(this.Button);
    
    			foreach (var trigger in triggers)
    			{
    				var navAction = trigger.Actions.OfType<Microsoft.Expression.Prototyping.Behavior.NavigateToScreenAction>().FirstOrDefault();
    				if (navAction != null)
    				{
    					MessageBox.Show(navAction.TargetScreen);
    				}
    			}
    		}
    	}
    }
    

    Monday, May 23, 2011 6:41 PM
    Moderator
  • Can you double check var navAction = trigger.Actions.OfType<Microsoft.Expression.Prototyping.Behavior.NavigateToScreenAction>().FirstOrDefault();

     

    For the life of me I can not port it to my project.  Essentially trigger does not have Actions as an associated method.

    Also,  Have you had a chance to run my example?  You will see that it can reference the property BUT the property is not referanceable AT RUN TIME and ONLY RUN TIME.

     

    Thanks in advance for your help.

     

     

    Monday, May 23, 2011 9:08 PM
  • Did you check the using statements to be sure you have all the required ones? (Possibly using System.Linq)

     

    I think the problem with your code is that NavToScreenButton is null at runtime, because it can't find it by name.

     

    Are you using WPF or Silverlight? I wrote my example in SL, but maybe it needs to be adjusted for WPF if that is what you are using.

    Monday, May 23, 2011 10:13 PM
    Moderator
  • Chuck,

     

    I think there is something afoot here... (I am using Sketchflow and feel more comfortable with CODE then Non-Code approaches for interactions) I was able to compile the source after adding the LINQ to the namespace (thanks I missed that) but the collection was empty... I tried various trickery to read any of the variables / objects but all are either null OR litterally hang the forloop WHICH DOES NOT raise an uncaught exception.

    I decided to see if I can get this working outside of a Sketchflow project and what I found now (using Silverlight) is that System.Windows.Interactivity is not a found namespace.  This I know means there is something wrong with my installation as I am compiling this right out of the Blend 4.0 installation and know that Blend is a requirement for the System.Windows.Interactivity name space.

     

    Any recommendations or should I perform a re-install?  (FYI - I recently updated to SP1 of Blend)

     

    Thanks

    Tuesday, May 24, 2011 1:47 PM
  • For the S.W.Interactivity reference not found, you probably just need to add a reference to your project's references to S.W.Interactivity.dll, SketchFlow projects have it in their template, but not regular SL projects. An easy way to get the reference is to drag a behavior from the asset panel to the artboard, Blend should add it automatically. If not, you can find it in a path similar to:

    "C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\Silverlight\v4.0\Libraries\System.Windows.Interactivity.dll"

    If that file can't be found, you may have to reinstall the Expression Blend SDKs. I don't believe that is likely to be the issue though.

     

    One difference is that my code ran in a separate button, not in the handler for the button that also has a navigation behavior. Can I ask what you are trying to accomplish here? Maybe I can suggest an easier idea.

    Tuesday, May 24, 2011 1:53 PM
    Moderator
  • Chuck,

     

    Thank you for your patience.  Here is what I am trying to do.  Keep in mind I am very new to Silverlight and Blend - but comfortable with C# (new as I am a Java programmer learning C#) using VS 2010.

    I am trying to prototype (sketchup) a logon page where the user will submit his/her userID and password plus select via a ComboBox the Role of the user.  I would like to Dynamically route the user to the appropriate page depending on the ComboBox selection.

     

    I had thought I could do this via dynamically setting the TargetScreen property in the ComboBox and triggering it off of a ClickEvent from the NavigationToScreenAction.

     

    Thanks for your help.

    Tuesday, May 24, 2011 3:09 PM
  • I can try to come up with a solution for you later, but for now, can you have a look at this and see if it might help you? http://electricbeach.org/?p=344

     

    It is doing something similar, conditionally choosing a page to navigate to in SketchFlow.

    Tuesday, May 24, 2011 3:32 PM
    Moderator
  • I was able to figure it out.  I of course research various issues until I found the solution that meets my specific requirement.  You will see it is a derivative of your original response.

     

    One benefit is now I can dynamically at run time set the TargetScreen property allowing NavigateToScreen action to be dynamically routed (with additional code but he fundemental is here).  I have also since found out how to dynamically read the selected value in my combo box (that is populated via a data collection) and with the code below route to the proper screen.

    Misc. Info:

    1.  MUST give the Object (Button, etc.) a name and set a default TargetScreen  in your XAML (can be done easily with the Blend UI).  I Called it LogonButton for my example

    2. MUST define System.Linq assemble/reference (thanks chuck)

     

    Example:

     System.Windows.Interactivity.TriggerCollection triggerCollection = Interaction.GetTriggers(this.LogonButton);
      
       
    foreach (System.Windows.Interactivity.TriggerBase trigger in triggerCollection)
       {
        
       
      var navAction =  (Microsoft.Expression.Prototyping.Behavior.NavigateToScreenAction) trigger.Actions.FirstOrDefault();
      
        MessageBox.Show("DEFAULT OR PRIORLY SET TargetScreen"+ navAction.TargetScreen);

     

    //Can at run time set TargetScreen property which will route to alternate page.


        navAction.TargetScreen = "name_space.name_of_page";
        
        MessageBox.Show("UPDATED TargetScreen" + navAction.TargetScreen);

        
       }

     



    • Marked as answer by stanglx Friday, May 27, 2011 2:57 PM
    Friday, May 27, 2011 2:56 PM