locked
My custom activity strategies/advices RRS feed

  • Question

  • Hi

    Please see the  jpeg file Url here, this is my Custom activity and i have some
    doubts/questions, i hope i make me understand:

    http://img44.imageshack.us/i/mycustomactivity.png/][IMG]http://img44.imageshack.us/img44/6049/mycustomactivity.th.png

    1- where you have "Ponderadores": i wish that when the user drop this activity on the
    workflow sequence, a list of my available variables (like size, price, capacity) appear
    and the user select what variable he want to use. actually i do this using a comboBox.

    2- where you see "Max.Limit": here the user insert a digit (long) and i do this using a
    normal textBox.

    3- on the blue border, i have here something similar with an if/else/then activity, but
    without the else part :), but my problem here is the button because the user can insert
    more then one conditions, can be 2, 3, 4, and so one... So my idea is to have a button
    like you see. And whe the user click on that button a Two VB expressionTextBoxes are
    created, under the first ones... One for condition and one for score. Do you have any
    idea how to do this?


    A great 2010 :) thanks in advance for the answer,

    Rui Martins


    • Edited by Rui M Monday, January 4, 2010 2:57 PM wrong words
    Monday, January 4, 2010 1:22 PM

Answers

  • Ah.  I think I understand.  The following code snippet adds a new in argument to a collection of InArgument<bool> in the activity (called Conditions), and then adds an expression editor to the list view (lv) in the activity designer when b1 is clicked.  etb_Loaded binds the expression editor to the argument just created.

    Note: This on it's own will not pick up existing arguments in the collection (so if you save close and reopen your workflow, you won't see the existing arguments in the collection), but the same logic can be used to initialize the list view (just iterate over ModelItem.Properties["Conditions"].Collection and use the same logic to create your expression editors).

            private void b1_Click(object sender, RoutedEventArgs e)
            {
                ModelItem.Properties["Conditions"].Collection.Add(new InArgument<bool>(true));
                ExpressionTextBox etb = new ExpressionTextBox();
                etb.ExpressionType = typeof(bool);
                etb.Loaded += new RoutedEventHandler(etb_Loaded);
               
                lv.Items.Add(etb);
            }

            void etb_Loaded(object sender, RoutedEventArgs e)
            {
                ExpressionTextBox etb = (ExpressionTextBox)sender;
                BindingOperations.SetBinding(
                        etb,
                        ExpressionTextBox.OwnerActivityProperty,
                        new Binding("ModelItem"));

                int index = ModelItem.Properties["Conditions"].Collection.Count - 1;

                BindingBase expressionBinding = new Binding()
                {
                    Path = new PropertyPath(String.Format("ModelItem.Conditions[{0}]", index.ToString())),
                    Converter = new ArgumentToExpressionConverter(),
                    Mode = BindingMode.TwoWay,
                };

                etb.SetBinding(
                    ExpressionTextBox.ExpressionProperty, expressionBinding);
            }

    Hope this helps,
    -Eric

    • Marked as answer by Rui M Monday, January 11, 2010 4:55 PM
    Thursday, January 7, 2010 7:52 PM

All replies

  • Hi Rui,

    I think I have a solution to your first question:

    The following 2 functions will walk up the model item tree and find a list of all unique variable names - Note: You may hit some strange errors if some of this or the parent activities contain a property called "Variables" that is not a collection of variables.  I've omitted that error check for clarity):

     private List<ModelItem> FindUniqueVariablesInScope(ModelItem element)
            {
                Dictionary<string, ModelItem> variables = new Dictionary<string, ModelItem>();
                while (element != null)
                {
                    ModelItemCollection variablesInElement = GetVariableCollection(element);
                    if (null != variablesInElement)
                    {
                        foreach (ModelItem modelVariable in variablesInElement)
                        {
                            LocationReference locationReference = modelVariable.GetCurrentValue() as LocationReference;
                            if (locationReference != null && !string.IsNullOrWhiteSpace(locationReference.Name) && !variables.ContainsKey(locationReference.Name))
                            {
                                variables.Add(locationReference.Name, modelVariable);
                            }
                        }
                    }
                    element = element.Parent;
                }
                return new List<ModelItem>(variables.Values);
            }

            private ModelItemCollection GetVariableCollection(ModelItem element)
            {
                if (null != element)
                {
                        ModelProperty variablesProperty = element.Properties["Variables"];
                        if (variablesProperty != null)
                        {
                            return variablesProperty.Collection;
                        }
                }
                return null;
            }

    We can then set the combobox items to this collection (cb is the combobox):

            void SetComboboxValues()
            {
                cb.Items.Clear();
                foreach (ModelItem item in FindUniqueVariablesInScope(ModelItem))
                {
                    cb.Items.Add(item.Properties["Name"].Value.ToString());
                }
            }

    And set up event handles on each of the parents to update the combo box when variables change or are added and deleted:


            protected override void OnModelItemChanged(object newItem)
            {
                ModelItem element = (ModelItem)newItem;
                while (element != null)
                {
                    if (element.Properties["Variables"] != null)
                    {
                        element.Properties["Variables"].Collection.CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(variablesInElement_CollectionChanged);
                        element.Properties["Variables"].Collection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(variablesInElement_CollectionChanged);
                    }
                    element = element.Parent;
                }
                SetComboboxValues();

                base.OnModelItemChanged(newItem);
            }

            void variablesInElement_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
            {
                SetComboboxValues();
            }


    I'm a little confused at what you are trying to do for numbers 2 and 3 though.  Can you clarify what you are trying to accomplish?  Adding your code for your custom activity might also help me understand what you want to do.

    Hope this helps,

    -Eric

    Tuesday, January 5, 2010 11:05 PM
  • Thanks Eric :)

    i will try to expose me more clearly.

    the second point os my previous post it´s done now, but my 3rd point it isn´t.

    So i just want to let the user define how much lines of "Condition - Score" (Th final part of my custom activity) he wish, now by default the user have one line of those, but i need that when the user click on the button the activity add in runtime one more line (or n lines - it depends of the user) of "Condition-Score".

    Thanks,

    Rui M
    Thursday, January 7, 2010 4:35 PM
  • Ah.  I think I understand.  The following code snippet adds a new in argument to a collection of InArgument<bool> in the activity (called Conditions), and then adds an expression editor to the list view (lv) in the activity designer when b1 is clicked.  etb_Loaded binds the expression editor to the argument just created.

    Note: This on it's own will not pick up existing arguments in the collection (so if you save close and reopen your workflow, you won't see the existing arguments in the collection), but the same logic can be used to initialize the list view (just iterate over ModelItem.Properties["Conditions"].Collection and use the same logic to create your expression editors).

            private void b1_Click(object sender, RoutedEventArgs e)
            {
                ModelItem.Properties["Conditions"].Collection.Add(new InArgument<bool>(true));
                ExpressionTextBox etb = new ExpressionTextBox();
                etb.ExpressionType = typeof(bool);
                etb.Loaded += new RoutedEventHandler(etb_Loaded);
               
                lv.Items.Add(etb);
            }

            void etb_Loaded(object sender, RoutedEventArgs e)
            {
                ExpressionTextBox etb = (ExpressionTextBox)sender;
                BindingOperations.SetBinding(
                        etb,
                        ExpressionTextBox.OwnerActivityProperty,
                        new Binding("ModelItem"));

                int index = ModelItem.Properties["Conditions"].Collection.Count - 1;

                BindingBase expressionBinding = new Binding()
                {
                    Path = new PropertyPath(String.Format("ModelItem.Conditions[{0}]", index.ToString())),
                    Converter = new ArgumentToExpressionConverter(),
                    Mode = BindingMode.TwoWay,
                };

                etb.SetBinding(
                    ExpressionTextBox.ExpressionProperty, expressionBinding);
            }

    Hope this helps,
    -Eric

    • Marked as answer by Rui M Monday, January 11, 2010 4:55 PM
    Thursday, January 7, 2010 7:52 PM
  • Hi again Eric,

    i already done it thanks.

    Do you know how i can add on my Properties (of the activity) the InArguments that i add to the collection?

    Like i have done to the Max limit expression box for example.

    Thanks a lot,

    Rui M. 
    Wednesday, January 13, 2010 5:47 PM
  • hi ,


     do you know how i can add to my properties the new inArgument conditions?

    and fo you know what i can do to not loose the design of my new expressionTextBoxes when i do collapse for example?


    thanks

    Rui M.
    Thursday, January 14, 2010 6:31 PM
  • Eric can you see another post of mine please,

    http://social.msdn.microsoft.com/Forums/en/wfprerelease/thread/840a34ea-758c-4220-b9ab-c6205f9d3acc

    it was great if you could help

    thanks

    Rui M.
    Friday, January 22, 2010 6:05 PM
  • Hi Rui,

    Sorry I missed the followup question.  To be honest I don't keep too close an eye on threads already marked as answered.

    At any rate, I've posted a reply to the other thread.

    -Eric

    Friday, January 22, 2010 6:55 PM
  • Thanks Eric :)

    i will try to expose me more clearly.

    the second point os my previous post it´s done now, but my 3rd point it isn´t.

    So i just want to let the user define how much lines of "Condition - Score" (Th final part of my custom activity) he wish, now by default the user have one line of those, but i need that when the user click on the button the activity add in runtime aac one more line (or n lines - it depends of the user) of "Condition-Score".

    Thanks,

    Rui M

    Thanks for your sharing! I understand this part.
    Wednesday, September 22, 2010 3:56 AM