locked
Does SourceLocationProvider.CollectMapping support WF 4.0.1 States? RRS feed

  • Question

  • I am trying to get locations of States and highlight them in WorkflowDesigner.

    CollectMapping is returning all other activity types, including those within states; but it does not return states.

    I see that State is not an Activity - http://msdn.microsoft.com/en-us/library/system.activities.statements.state.aspx - it inherits from Object !

     

     

    The state obviously has a location on the designer (I can see it in the XAML ViewState)

                  <State x:Name="__ReferenceID1" DisplayName="State2" sap:VirtualizedContainerService.HintSize="113.6,60.8">
                   <sap:WorkflowViewStateService.ViewState>
                      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                        <av:Point x:Key="ShapeLocation">23.2,209.6</av:Point>
                        <av:Size x:Key="ShapeSize">113.6,60.8</av:Size>
                        <x:Boolean x:Key="IsPinned">False</x:Boolean>
                      </scg3:Dictionary>
                    </sap:WorkflowViewStateService.ViewState>

     -I can get States from designer using the ModelingService.

    I have retrieved the viewstate programatically - from here I can retrieve its ShapeLocation.

                var viewStateService = _workflowDesigner.Context.Services.GetService<ViewStateService>();
                var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();
                var modelItems = modelService.Find(modelService.Root, typeof(State));
                var activities = WorkflowInspectionServices
                    .GetActivities(_rootActivity)
                    .Where(a => a.GetType().FullName == "System.Activities.Statements.InternalState");
     
                foreach (var modelItem in modelItems)
                {
                    var state = modelItem.GetCurrentValue() as State;
                    var stateId = activities
                        .Where(a => a.DisplayName == state.DisplayName)
                        .Select(a => a.Id)
                        .First();
                    var viewState = viewStateService.RetrieveAllViewState(modelItem);
                    var shapeLocation = (Point)viewState["ShapeLocation"] ;
                }

     However, this is just a Point. How do I get a SourceLocation ? (linestart, columnStart, lineEnd, columnEnd)?

    Using reflection I can see that SourceLocationProvider.TryGetSourceLocation uses

    AttachablePropertyServices.TryGetProperty<int>(obj, XamlDebuggerXmlReader.StartLineName, out startLine)
    

    to get lineStart.

    I can see that

    AttachablePropertyServices.CopyPropertiesTo 

    gives me an array containing HintSize and ViewState, which dont have anything to do with SourceLocation fields

    Can I use AttachablePropertyServices to get SourceLocation for State?

    Can I use this SourceLocation to set

    WorkflowDesigner.DebugManagerView.CurrentLocation
    

     to highlight a specific state?







    Wednesday, June 1, 2011 6:21 PM

Answers

  • In the end, it looks like I cannot easily get a State's SourceLocation. 

    For StateMachine Tracking Visualization, a workarround is in order:

    As WorkflowDesigner.View is a WPF UIElement, I can use VisualTreeHelper - see http://krishnabhargav.blogspot.com/2008/10/visual-tree-helper-methods.html for generic recursive traversal method GetChildrenOfType<T>

     

    private void SelectState(string stateName)
            {
                var borders = GetChildrenOfType<Border>(RehostGrid).Where(b => b.Name == "ShapeBorder").ToList();
                foreach (var b in borders)
                {
                    var isRoot = GetChildrenOfType<TextBlock>(b).Where(t => t.Text == "StateMachine").Any();
                    var containsTargetState = GetChildrenOfType<TextBlock>(b).Where(t => t.Text == stateName).Any();
     
                    if (!isRoot && containsTargetState)
                    {
                        b.BorderBrush = new SolidColorBrush(Colors.Yellow);
                        b.BorderThickness = new Thickness(4);
                    }
                    else
                    {
                        b.BorderBrush = new SolidColorBrush(Colors.White);
                        b.BorderThickness = new Thickness(0);
                    }
     
                }
            }

     

    A truly atrocious 'state' of affairs! 

     

     

     

    • Marked as answer by JReuben1 Sunday, June 5, 2011 9:26 AM
    Sunday, June 5, 2011 9:26 AM

All replies

  • SO, in a State Machine, how can I get the SourceLocation of a State ?

     

    Friday, June 3, 2011 9:13 PM
  • In the end, it looks like I cannot easily get a State's SourceLocation. 

    For StateMachine Tracking Visualization, a workarround is in order:

    As WorkflowDesigner.View is a WPF UIElement, I can use VisualTreeHelper - see http://krishnabhargav.blogspot.com/2008/10/visual-tree-helper-methods.html for generic recursive traversal method GetChildrenOfType<T>

     

    private void SelectState(string stateName)
            {
                var borders = GetChildrenOfType<Border>(RehostGrid).Where(b => b.Name == "ShapeBorder").ToList();
                foreach (var b in borders)
                {
                    var isRoot = GetChildrenOfType<TextBlock>(b).Where(t => t.Text == "StateMachine").Any();
                    var containsTargetState = GetChildrenOfType<TextBlock>(b).Where(t => t.Text == stateName).Any();
     
                    if (!isRoot && containsTargetState)
                    {
                        b.BorderBrush = new SolidColorBrush(Colors.Yellow);
                        b.BorderThickness = new Thickness(4);
                    }
                    else
                    {
                        b.BorderBrush = new SolidColorBrush(Colors.White);
                        b.BorderThickness = new Thickness(0);
                    }
     
                }
            }

     

    A truly atrocious 'state' of affairs! 

     

     

     

    • Marked as answer by JReuben1 Sunday, June 5, 2011 9:26 AM
    Sunday, June 5, 2011 9:26 AM
  • Hi

    This is exactly what I'm after, however when ever I try to run this code it always returns 0 Boarders :(

    Your RehostGrid, can I assume this is just a normal Grid?

    I've tried passing in a grid with the WorkFlowDesigner.View as a child, and I've also tried passing in the workflowDesigner.View. I've also walked through the code and notice that when it walks the visual tree and gets down to a parent of System.Activities.Presentation.View.DesignView it stops, it doesn't navigate down the Content path.

    Below is an example of my code:

    private void LoadWorkflow()
          {
             (new DesignerMetadata()).Register();  //Registers the runtime metadata.
             var dm = new DesignerMetadata();
             dm.Register();
             
             var wd = new WorkflowDesigner();
             var fileName = @"..\TestProcess.xaml";
             wd.Text = File.ReadAllText(fileName);
             wd.Load();
             Grid.SetColumn(wd.View, 0);
             Grid.SetRow(wd.View, 0);
             _progressGrid.Children.Add(wd.View);
    
             var designerView = wd.Context.Services.GetService<DesignerView>();
             designerView.WorkflowShellBarItemVisibility = 
             ShellBarItemVisibility.MiniMap |
             ShellBarItemVisibility.Zoom;
    
              SelectState("Inputting");
          }
    Any help would be really appricated, I thought we had the visual tracking sorted until I ran into the Statemachine and the different ways it worked.Thank you.Steve.

     


    Steve G

    Friday, March 9, 2012 5:45 PM