none
Can I get the activity designer from a model item?

    Question

  • Hi,

    I'm not sure if this makes sense, but what I'd like to do is get the activity designer associated with a given model item.  I realize that not every model item is an activity (and therefore, wouldn't have an activity designer).  In my case, I'm using the ModelService modelchanged event.  I then examine the ModelChangedEventArgs and the ItemsAdded collection.  If a given model item in that collection is a FlowDecision, for example, I want to get that activity's designer.  I tried using ModelItem.View, after confirming that model item is a FlowDecision, but ModelItem.View is null.

    Is it possible to get an ActivityDesigner from a model item (assuming that model item is representing an activity)?

    UPDATE: My code for the model changed event looks like this:

            private void modelService_ModelChanged(object sender, ModelChangedEventArgs e)
            {
                if (e.ItemsAdded != null)
                {
                    foreach (ModelItem mi in e.ItemsAdded)
                    {
                        if (mi.GetCurrentValue() is FlowDecision)
                        {
                            WorkflowViewElement flowDecisionActivityDesigner = mi.View as WorkflowViewElement;
                            if (flowDecisionActivityDesigner != null)
                            {

                            }
                        }
                    }
                }

    In this case, mi.View returns null, as originally discussed.  However, if I attach my logic to a button (in a rehosted designer) and walk the model item tree until I find the same model item (the FlowDecision), and then call ModelItem.View, the return value is not null, but is the activity designer, as expected.  Am I doing something wrong, or is this a bug?


    Thanks,
    Notre

    • Edited by Notre Friday, January 08, 2010 7:43 PM Changed code sample to use WorkflowViewElement rather than AcitivtyDesigner, as FlowChart designer doesn't inherit from ActivityDesigner
    Friday, January 08, 2010 7:23 PM

Answers

  • sorry for the late response.
    let me conclude this problem
    as you said when you drop an activity, the item.View is null, right?

    this is because you bind the event to modelchange
    so when the model changed, the model item has been added, but the view for this item hasn't been added.

    so my advice for the most safe way to get the view

    if(item.View == null)
    {
         //use ViewService.GetView to get the view of item
    }
    else
    {
         //use item.view directly to get the view of item.
    }




    I noitced that if I dropped an activity after the WriteLine activity in the sequence, then everything works fine.

    If instead I drop an actiivty (from the toolbox) before the WriteLine activity in the sequence. then temp.View returns null.

    explaination: if you drop the activity before the writeline activity in sequence, the new dropped activity become Activities[0], in the sample code I offered, it just get the first activity's view. so at this time, the new dropped item is the first activity, and the model item is added, so the model event is invoked, but the view hasn't been generated that time.

    this is why when you dopped the activity before writeline temp.View is null.

    • Marked as answer by Notre Monday, January 11, 2010 11:50 PM
    Monday, January 11, 2010 11:14 PM
  • ok. so let me answer your original questions.

    if you want to get the designer of flowswitch or flowdecision
    you can use following code

    designer.Context.Services.GetService<ViewService>().GetView(temp)


    temp is the modelitem of flowdecision
    designer is the WorkflowDesigner

    I assue you are working on the rehost app.
    Friday, January 08, 2010 10:00 PM

All replies

  • Updated problem description above.

    Thanks,
    Notre
    Friday, January 08, 2010 7:31 PM
  • can I ask what you want to do with the activity designer?
    Friday, January 08, 2010 7:44 PM
  • I assume you are in the rehost app.
    then you can use following to get the activity designer.

    assume that you have a rehost app, and there is an assign designer on the designer surface

    designer.Context.Services.GetService<

     

    ViewService>().GetView(assignModelItem)


    then you can get AssignDesigner
    Friday, January 08, 2010 7:58 PM
  • I have a couple of things in mind.  The first thing I want to do is, with any out of the box activities that have an ExpressionTextBox, I don't want to display the "Enter a VB Expression" hint text.  One way I can think of achieving this is to completely replace the activity designer for these out of the box activities with an activity designer of my own. 

    Another approach I was thinking of is, if I can get the built in activity designer, then I can hopefully find any ExpressionTextBox controls on the designer, and set the HintText property to something more appropriate for my user base.  I'm not exposing VB to our workflow users, so this hint text is bad, from my perspective.  I've already entered a connect bug regarding this hint text, but it has been postponed for fixing post RTM, so I'm looking for workarounds. I realize that the FlowDecision does not have an ExpressionTextBox on its activity designer, but there may be other out of the box activities I may still wish to reuse, that do surface an ExpressionTextBox on the design surface.

    A second thing I'm thinking of doing is to some adornment type things on the activity designers, but I'm not clear on the exact use case(s) yet.  (One might be for simulating debugging in a rehosted designer; I know Kshal Shah did some stuff on that).

    I think I will find more use cases as I dig deeper, so being able to get at the activity designer will likely be useful as I progress further.

    Thanks,
    Notre

    Friday, January 08, 2010 8:02 PM
  • ok. so let me answer your original questions.

    if you want to get the designer of flowswitch or flowdecision
    you can use following code

    designer.Context.Services.GetService<ViewService>().GetView(temp)


    temp is the modelitem of flowdecision
    designer is the WorkflowDesigner

    I assue you are working on the rehost app.
    Friday, January 08, 2010 10:00 PM
  • Hi Ye Yu,

    Yes, I'm working on a rehosted app.  I tried what you suggested and it does resolve my original question.  I may post another, separate question to ask about finding the ExpressionTextBox controls on a given activity designer but I'll try to figure that out myself first.

    Thanks,

    Notre
    Friday, January 08, 2010 10:27 PM
  • add some more detail.
    you can also use modelitem.view to get the workflowviewelement, but you need to put the modelitem of the activity designer which is not wrapped by flowstep.
    Saturday, January 09, 2010 6:42 AM
  • I'm afraid I don't follow this last point, Ye Yu.

    ModelItem.View is returning null in the code I use above.  How do I get the model item of the activity designer that is not wrapped by the flowstep?

    Update: I think I can get the model item of the activity designer by writing code like this:

                        ///more stuff above, assume WriteLine actiivity dropped on FlowChart -- therefore wrapped in FlowStep
                        if (mi.ItemType == typeof(FlowStep))
                        {
                            ModelItem actionMi = mi.Properties["Action"].Value;
                            object designer = actionMi.View; //designer is still null!
    However, calling .View, still returns null!

    • Edited by Notre Monday, January 11, 2010 5:40 PM Add proposed way of getting non-wrapped model item
    Monday, January 11, 2010 5:01 PM
  • I assume your root activity is flowchart.
    then you can use following code to get the workflowviewelement

     ModelItem temp = root.Properties["Nodes"].Collection[0].Properties["Action"].Value;

    WorkflowViewElement ele = temp.View as WorkflowViewElement;


    can you refer to this link? I have put complete code about how to get the activity designer, how to get all the controls on the activity designer, and how to modify the hint text of ETB there

    http://social.msdn.microsoft.com/Forums/en-US/wfprerelease/thread/d5758c2b-58eb-459e-b608-322e467fbac3

    Monday, January 11, 2010 7:04 PM
  • One comment to the ModelItem.View, before the rehost app is launched, the modelitem.view is null.
    it will get the view designer after the rehost app is launched.
    Monday, January 11, 2010 8:08 PM
  • Hi Ye Yu,

    My root activity is FlowChart, but that in turn is wrapped in an ActivityBuilder.

    I can see how this would work:

      ModelItem temp = root.Properties["Nodes"].Collection[0].Properties["Action"].Value;


    but really this is the same as this:

      ModelItem actionMi = mi.Properties["Action"].Value;

    I think where ModelItem.View seems to be breaking down is when I'm using a model item obtained from the  ModelService modelchanged event, as originally reported in this forum post.  If I walk the model item tree in response to a button click event, as you do in your sample in the other thread, and as I noted in the original post then ModeItem.Vuew does not returns null.

    Thanks,
    Notre
    • Edited by Notre Monday, January 11, 2010 8:15 PM correct last sentence
    Monday, January 11, 2010 8:12 PM
  • I think when you see the modelItem.view is null, it's because the rehost app hasn't been launched, you try to get the ModelItem.View before the rehost app is launched, right?
    Monday, January 11, 2010 8:17 PM
  • No, that's not what's happening for me.  When I drop a new activity (from the toolbox) onto the design surface, ModelService modelchanged event is called.  At that point, ModelItem.View is null.

    Notre
    Monday, January 11, 2010 8:32 PM
  • To add to the above point, it almost seems like the model item is not fully initialized, by the time the ModelService modelchanged event is called, even if this is response to adding a new activity to the workflow (by drag and drop onto the design surface).

    Notre
    Monday, January 11, 2010 8:46 PM
  • Your sample above works for me (sets left hand side ExpressionTextBox HinText to "test" of Assign activity) .  Immediate differences between my code and yours - I'm using a FlowChart rather than Sequence, and I'm trying with a WriteLine activity rather than Assign activity.

    EDIT: Your last sample seems to have been deleted? (Hope I didn't do it).

    Notre
    • Edited by Notre Monday, January 11, 2010 9:18 PM update text
    Monday, January 11, 2010 9:13 PM
  • If I change your sample code (which appears to have been deleted) like this:

                Sequence seq = new Sequence();
                //seq.Activities.Add(new Assign());
                seq.Activities.Add(new WriteLine());

    then when modelChanged gets called:

    void designer_ModelChanged(object sender, EventArgs e)
            {
                ModelItem root = designer.Context.Services.GetService<ModelService>().Root;
                ModelItem temp = root.Properties["Implementation"].Value.Properties["Activities"].Collection[0];
                WorkflowViewElement ele = temp.View as WorkflowViewElement;
                ((ExpressionTextBox)(((System.Windows.Controls.Grid)(ele.Content)).Children[0])).HintText = "test";
            }

    It throws an exception on the last statement:

    Unable to cast object of type System.Windows.Controls.TextBlock to 'Systeem.Activities.Presetnation.View.ExpressTextBox'.  I must be indexing into the control wrong, to find the ExpressionTextBox...

    Notre

    Monday, January 11, 2010 9:21 PM
  • yes, if you want to find the ETB on writeline activity designer, you need to use

     ((ExpressionTextBox)(((System.Windows.Controls.Grid)(ele.Content)).Children[1])).HintText = "test"; instead.
    Monday, January 11, 2010 10:00 PM
  • Ok, that code change worked for WriteLine actiivty; thanks.

    I noitced that if I dropped an activity after the WriteLine activity in the sequence, then everything works fine.

    If instead I drop an actiivty (from the toolbox) before the WriteLine activity in the sequence. then temp.View returns null.
    Monday, January 11, 2010 10:14 PM
  • sorry for the late response.
    let me conclude this problem
    as you said when you drop an activity, the item.View is null, right?

    this is because you bind the event to modelchange
    so when the model changed, the model item has been added, but the view for this item hasn't been added.

    so my advice for the most safe way to get the view

    if(item.View == null)
    {
         //use ViewService.GetView to get the view of item
    }
    else
    {
         //use item.view directly to get the view of item.
    }




    I noitced that if I dropped an activity after the WriteLine activity in the sequence, then everything works fine.

    If instead I drop an actiivty (from the toolbox) before the WriteLine activity in the sequence. then temp.View returns null.

    explaination: if you drop the activity before the writeline activity in sequence, the new dropped activity become Activities[0], in the sample code I offered, it just get the first activity's view. so at this time, the new dropped item is the first activity, and the model item is added, so the model event is invoked, but the view hasn't been generated that time.

    this is why when you dopped the activity before writeline temp.View is null.

    • Marked as answer by Notre Monday, January 11, 2010 11:50 PM
    Monday, January 11, 2010 11:14 PM
  • Ok, that is quite helpful. Thanks for clarifying the problem for me.

    Notre
    Monday, January 11, 2010 11:50 PM