locked
How do I access XamlActivity context? RRS feed

  • Question

  • Hi all,

    I'm trying to implement a XamlActivity with some added functionality (the idea is to have a rehosted flowchart that also act as a switch, this will be used to build custom menu switches),

     

    The way I did it is to add a Partial code class and implement the interfaces I needed (So I have the XamlActivity and the corresponding cs file), 

    Problem is that for me to evaluate the Condition (InOutArgument) I need the context, the way I normally do it is by overriding the Execute() method, but in Xaml activity there is no such option.

     

    I need to access the context somehow so I can get the decapsulated value inside the argument.

    Is there anyway to do it?

    (maybe get to some callback method or something?)

     

    Hope anyone can help me here,

    Thanks in advance,

    Eyal...


    • Edited by Quesso Levy Wednesday, July 20, 2011 7:52 AM miss type
    Wednesday, July 20, 2011 7:50 AM

All replies

  • You can only override Execute() for class CodeActivity, CodeActivity<T>, NativeActivity, etc - not Activity. Note that these are actually different Execute() methods, taking different contexts - there isn't a common Execute method between those classes. Activity.Execute() does not exist.

    (And using Xaml with <x:Activity Class="... " /> means that you are subclassing System.Activities.Activity.)
    Tim

    Thursday, July 21, 2011 3:58 AM
  • Thanks for the reply Tim,

     

    Still the problem is how do I access the data held in the OutArgument of my Activity.

     

    The thing is that I have a parent activity (NativeActivity) that schedules the activity (which in turn sets an OutArgument I need  to proceed) and needs to retrieve the value within the OutArgument,

    How do I access the value set in OutARgument by the child Activity from the parent?

     

    Hope I'm being clear enough,

     

    Any help will be appreciated,

    Quesso..


    Thursday, July 21, 2011 4:15 PM
  • I think the way to do it is (depending on visibility) either:

    if it is an implementation child, in the parent native activity, just bind the outargument of the child to an implementation variable of your native activity, then you can get the value from the variable once the child finished executing.

    or

    if it is a public child, in the parent native activity, you can schedule the child wrapped inside of an ActivityFunc<T> (where your OutArgument is OutArgument<T>) -and bind the Result of the activity func to the ActivityFunc's DelegateOutArgument.

    ScheduleFunc doc.

    Tim


    Thursday, July 21, 2011 8:04 PM
  • Hey Tim,

     

    This is the way I did it (code attached), the parent activity is a NativeActivity, the child is a Xaml Activity:

     

    Parent:

     

    public class EthrixEvoipMenu1 : NativeActivity
     {
    
    
     private Dictionary<string, object> inputs = new Dictionary<string, object>();
     
     private ActivityFunc<string, object> Body { get; set; }
    
     protected override void CacheMetadata(NativeActivityMetadata metadata)
     {
      var arg = new DelegateInArgument<string>();
    
      Body = new ActivityFunc<string, object>
      {
      Argument = arg,
      Handler = new EthrixEvoipMenuXamlView1  //The Activity I try to wrap and run
      {
    
       //This is the OutArgument I'm trying to access 
       Condition = arg
      }
      };
    
      metadata.AddImplementationDelegate(Body);
      base.CacheMetadata(metadata);
     }
    
     protected override void Execute(NativeActivityContext context)
     {
      context.ScheduleFunc<string, object>(Body, "1", ChildCompletionCallback);
    
     }
    
     private void ChildCompletionCallback(NativeActivityContext context, ActivityInstance completedInstance, object result)
     {
    
     }
    
     }
    

     


    I expected the access the Condition OutArgument in the Result somehow (maybe I'm setting the result Ok?),

    I know I'm pretty close but not quite there yet,

     

    The Xaml activity code (the child activity, not that it matters much) is :

     

    <Activity mc:Ignorable="sap" x:Class="WorkflowConsoleApplication4.EthrixEvoipMenuXamlView1" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:ef="clr-namespace:Ethrix.Flow;assembly=Ethrix.Flow" xmlns:eft="clr-namespace:Ethrix.Flow.Transitions;assembly=Ethrix.Flow" xmlns:eiav="clr-namespace:Ethrix.IVRFlow.Activitys.Voice;assembly=Ethrix.IVRFlow.Activitys" xmlns:esti="clr-namespace:Ethrix.SipServer.ToolBox.Interfaces;assembly=Ethrix.SipServer.ToolBox.Interfaces" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <x:Members>
     <x:Property Name="Condition" Type="OutArgument(x:String)" />
     <x:Property Name="ToolBox" Type="InArgument(esti:IToolBox)" />
     </x:Members>
     <sap:VirtualizedContainerService.HintSize>654,676</sap:VirtualizedContainerService.HintSize>
     <mva:VisualBasic.Settings>Assembly references and imported namespaces for internal implementation</mva:VisualBasic.Settings>
     <ef:IVRFlow ToolBox="{x:Null}" sad:XamlDebuggerXmlReader.FileName="E:\test projects\17_4_workflowTest\24_4_Workflow\WorkflowConsoleApplication4\EthrixEvoipMenuXamlView1.xaml" sap:VirtualizedContainerService.HintSize="614,636">
     <ef:IVRFlow.Entry>
     <ef:StartNode x:Name="__ReferenceID0" DisplayName="Start">
     <sap:WorkflowViewStateService.ViewState>
      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
      <av:Size x:Key="ShapeSize">90,58</av:Size>
      </scg3:Dictionary>
     </sap:WorkflowViewStateService.ViewState>
     </ef:StartNode>
     </ef:IVRFlow.Entry>
     <ef:IVRFlow.TransitionsCollection>
     <eft:Transition DisplayName="{x:Null}" Source="{x:Reference __ReferenceID0}" TransitionGroup="{x:Null}">
     <sap:WorkflowViewStateService.ViewState>
      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
      <av:PointCollection x:Key="ConnectorLocation">290,73 290,416</av:PointCollection>
      </scg3:Dictionary>
     </sap:WorkflowViewStateService.ViewState>
     <eft:Transition.To>
      <Assign x:Name="__ReferenceID1">
      <Assign.To>
      <OutArgument x:TypeArguments="x:String">[Condition]</OutArgument>
      </Assign.To>
      <Assign.Value>
      <InArgument x:TypeArguments="x:String">2</InArgument>
      </Assign.Value>
      <sap:WorkflowViewStateService.ViewState>
      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
      <av:Point x:Key="ShapeLocation">169,416</av:Point>
      <av:Size x:Key="ShapeSize">242,58</av:Size>
      </scg3:Dictionary>
      </sap:WorkflowViewStateService.ViewState>
      </Assign>
     </eft:Transition.To>
     </eft:Transition>
     </ef:IVRFlow.TransitionsCollection>
     <sap:WorkflowViewStateService.ViewState>
     <scg3:Dictionary x:TypeArguments="x:String, x:Object">
     <x:Boolean x:Key="IsExpanded">False</x:Boolean>
     <x:Double x:Key="StateContainerWidth">600</x:Double>
     <x:Double x:Key="StateContainerHeight">600</x:Double>
     </scg3:Dictionary>
     </sap:WorkflowViewStateService.ViewState>
     <x:Reference>__ReferenceID0</x:Reference>
     <x:Reference>__ReferenceID1</x:Reference>
     </ef:IVRFlow>
    </Activity>
    

     

    How can I access the value of the Condition OutArgument in the parent activity? (just to remind what is my question in all this mess :)),

    Am I running the ActivityFunc currectly?

     

    Thanks alot in advance,

    Eyal.



    • Edited by Quesso Levy Monday, July 25, 2011 7:44 AM Code fixes
    Monday, July 25, 2011 7:06 AM
  • If you set the ActivityFunc.Result to a DelegateOutArgument, then I think you should be able to read it from the , object result) parameter in your completion callback.
    Tim
    Monday, July 25, 2011 8:25 PM
  • Thanks alot for the reply again Tim,

    Could't get it to work (Though I will get back to it as soon as I clear up on assignments),

     

    We actually implemented a workaround (Xaml file is the same), The Cs parent class is as such:

    //IVRAsyncCodeActivity is an AsyncCodeActivity with added Properties
    public class EthrixEvoipMenu1 : IVRAsyncCodeActivity
     {
    
     //Enter the Xaml activity with the menu here (create a new EthrixEvoipMenuXamlView to 
     //serve as the menu xaml) 
     static EthrixEvoipMenuXamlView1 ethrixEvoipMenuXamlView = new EthrixEvoipMenuXamlView1();
     static bool ethrixEvoipMenuXamlViewIsCached = false;
    
     private object caseEval = "";
    
     private AsyncCallback callback;
    
     //Placebo async result
     private ActivityAsyncResult asyncresult;
    
     [Browsable(false)]
     public string ActivityTemplateIconName { get; set; }
    
     protected override void CacheMetadata(CodeActivityMetadata metadata)
     {
     if (!ethrixEvoipMenuXamlViewIsCached)
     {
     //Caching static Activity only once
     WorkflowInspectionServices.CacheMetadata(ethrixEvoipMenuXamlView);
     ethrixEvoipMenuXamlViewIsCached = true;
     }
    
     base.CacheMetadata(metadata);
     }
    
     protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
     {
     Dictionary<string, object> inputs = new Dictionary<string, object>();
      
     //An argument I use inside the Activity I run
     inputs.Add("ToolBox", this.ToolBox.Get(context));
    
     WorkflowApplication app = new WorkflowApplication(ethrixEvoipMenuXamlView, inputs);
    
     this.callback = callback;
     this.asyncresult = new ActivityAsyncResult(state);
    
     //Upon completion we take the Condition (This is what I needed out of the child activity)
     app.Completed = (WorkflowApplicationCompletedEventArgs x) =>
     {
     x.Outputs.TryGetValue("Condition", out caseEval);
    
     //Invoke the callback to end the activity
     this.callback.Invoke(this.asyncresult);
     };
    
     app.Run();
    
     return this.asyncresult;
     }
    
     protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
     {
    
     }
     }
    

     

    Instead of running the Activity we run another inner workflow, Guess performance will suffer a bit but it's a much simpler solution and time is pressing (as always :)),

     

    Actually I'm amazed how hard this (what I expected to be) simple communication between parent and child is,
    Guess Ill have to better learn it in the future.

     

    Thanks for your time Tim.

    Eyal. 




    • Edited by Quesso Levy Tuesday, July 26, 2011 2:49 PM removed un needed code to increase clarity
    Tuesday, July 26, 2011 8:31 AM