locked
AttachedProperty not updating ModelItem via PropertyGrid but does via designer control binding RRS feed

  • Question

  • I have an attached property on my ModelItem for a WF4 activity designer. The attached property is browsable via the property grid and is also hooked up to a control on the activity designer. The attached property makes a change to a property defined on the activity and then makes additional changes to the ModelItem based on the new property value.

    Modifying the attached property value via the control in the designer works as expected and the ModelItem reflects the updated change to the activity property.

    Modifying the attached property value via the property grid does not work as expected. The ModelItem does not reflect the updated change to the activity property.

    I am guessing there is a difference between the ModelItem provided from the property grid compared to the ModelItem provided from the activity designer.

     

     private void AttachArgumentsProperty(ModelItem modelItem, AttachedPropertiesService attachedPropertiesService)
     {
     AttachedProperty<GenericArgumentCount> argumentsProperty = new AttachedProperty<GenericArgumentCount>
      {
       Name = Arguments, 
       IsBrowsable = true, 
       OwnerType = modelItem.ItemType, 
       Getter = delegate(ModelItem modelReference)
        {
        return
         (GenericArgumentCount)
         modelReference.Properties[ArgumentCount].ComputedValue;
        }, 
       Setter = delegate(ModelItem modelReference, GenericArgumentCount newValue)
        {
        _previousArguments =
         (GenericArgumentCount)
         modelReference.Properties[ArgumentCount].ComputedValue;
    
        
    // NOTE: The following line when executed from the property grid
    // does not work. The ComputedValue remains as the original value
    // after this line of code has been executed
    modelReference.Properties[ArgumentCount].ComputedValue = newValue;
    
        // Update the activity to use InstanceResolver with the correct number of arguments
        UpgradeInstanceResolverType(modelReference);
        }
      };
    
     attachedPropertiesService.AddProperty(argumentsProperty);
     }
    

    Any ideas?

     



    Thursday, August 18, 2011 3:39 AM

Answers

  • I found a page on MSDN that addresses the type of argument to use on activities - http://msdn.microsoft.com/en-us/library/gg281650.aspx. This lead me to leave my property as a standard CLR property as this is appropriate for the purpose of the custom activity.

    This article did however indicate the fix for this issue. The reason that MorphHelper.MorphProperties didn't copy across the property is because the property is a CLR property and is considered immutable (for lack of a more appropriate word) relative to the activity instance.

    So the fix was to include a constructor for which I could provide the new value for the CLR property and then create the new model item from that value rather than trying to get MorphHelper to do it for me. This now works as expected. 

    FYI, the morph code looks like this now:

    public static void UpdateModelType(ModelItem modelItem, Type newType, GenericArgumentCount previousArguments)
    {
      Boolean displayNameRequiresUpdated = HasDefaultDisplayName(modelItem);
      GenericArgumentCount originalArgumentCount = GetArgumentCount(modelItem);
      EditingContext editingContext = modelItem.GetEditingContext();
      Object instanceOfNewType = Activator.CreateInstance(newType, originalArgumentCount);
      ModelItem newModelItem = ModelFactory.CreateItem(editingContext, instanceOfNewType);
    
      using (ModelEditingScope editingScope = newModelItem.BeginEdit("Change type argument"))
      {
        MorphHelper.MorphObject(modelItem, newModelItem);
        MorphHelper.MorphProperties(modelItem, newModelItem);
    
        if (displayNameRequiresUpdated)
        {
          ForceDisplayNameUpdate(newModelItem);
        }
    
        DesignerUpdater.UpdateModelItem(modelItem, newModelItem);
    
        editingScope.Complete();
      }
    }
    


    • Marked as answer by Rory_Primrose Thursday, August 25, 2011 3:52 AM
    Thursday, August 25, 2011 3:52 AM

All replies

  • Hi, Rory

    You probably have checked this sample from MSDN:
    http://msdn.microsoft.com/en-us/library/ee834515.aspx

    To achieve the same dynamic effect as you have done in Activity designer. you can create a custom property editor, the editor itself will managed the changing/display/hide.

    Hope this helps
    Regards
    MSDN Community Support
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    This posting is provided "AS IS" with no warranties, and confers no rights. My Blog: http://xhinker.com
    Microsoft Windows Workflow Foundation 4.0 Cookbook
    Wednesday, August 24, 2011 1:51 AM
  • Hi Andrew,

    I am not using a custom property editor via the property grid. The property is bound in an enum type.

    I suspect that the reason that the property isn't being updated against the ModelItem is because the property is an standard property (T) rather than an Argument<T> property. I'll test out this theory a little later and put the result back here.

    There doesn't seem to be much information out there about when it is appropriate to use a standard property type vs Argument<T> properties on customer activities.

    Any thoughts/pointers?

    Wednesday, August 24, 2011 1:57 AM
  • I found a page on MSDN that addresses the type of argument to use on activities - http://msdn.microsoft.com/en-us/library/gg281650.aspx. This lead me to leave my property as a standard CLR property as this is appropriate for the purpose of the custom activity.

    This article did however indicate the fix for this issue. The reason that MorphHelper.MorphProperties didn't copy across the property is because the property is a CLR property and is considered immutable (for lack of a more appropriate word) relative to the activity instance.

    So the fix was to include a constructor for which I could provide the new value for the CLR property and then create the new model item from that value rather than trying to get MorphHelper to do it for me. This now works as expected. 

    FYI, the morph code looks like this now:

    public static void UpdateModelType(ModelItem modelItem, Type newType, GenericArgumentCount previousArguments)
    {
      Boolean displayNameRequiresUpdated = HasDefaultDisplayName(modelItem);
      GenericArgumentCount originalArgumentCount = GetArgumentCount(modelItem);
      EditingContext editingContext = modelItem.GetEditingContext();
      Object instanceOfNewType = Activator.CreateInstance(newType, originalArgumentCount);
      ModelItem newModelItem = ModelFactory.CreateItem(editingContext, instanceOfNewType);
    
      using (ModelEditingScope editingScope = newModelItem.BeginEdit("Change type argument"))
      {
        MorphHelper.MorphObject(modelItem, newModelItem);
        MorphHelper.MorphProperties(modelItem, newModelItem);
    
        if (displayNameRequiresUpdated)
        {
          ForceDisplayNameUpdate(newModelItem);
        }
    
        DesignerUpdater.UpdateModelItem(modelItem, newModelItem);
    
        editingScope.Complete();
      }
    }
    


    • Marked as answer by Rory_Primrose Thursday, August 25, 2011 3:52 AM
    Thursday, August 25, 2011 3:52 AM
  • Just mention that I'm finding the answer mysterious as

    a) the original question didn't mention MorphHelper

    and

    b) AFAIK MorphHelper.MorphProperties does copy plain old CLR properties- they just have to match all the obvious constraints (same name, same type, public, gettable, settable)

    Tim

    Saturday, August 27, 2011 5:37 AM
  • Hi Tim,

    Yes you are right, the original question didn't mention MorphHelper. At the time, I was more concerned about why the attached property was not able to update the ModelItem. MorphHelper was presenting a similar issue where MorphProperties was also not carrying across this value. The workaround I posted was the only way I was able to get this to work the way I expected.

    Tuesday, August 30, 2011 4:21 AM
  • Did you also figure out the original issue?
    Tim
    Thursday, September 1, 2011 5:04 AM
  • Unfortunately no. I'm really at a loss on that one as this was the way the code originally worked. The delegate on the attached property updated the model item property that pointed to a CLR property.

    The workaround I posted has been the only way I could get the outcome I was after. A combobox on the designer now binds to the CLR property rather than the attached property which has now been removed (it was really just a wrapper for change notification anyway). I hook into the item change event of the combobox in the designer to know when the CLR property has been changed in the designer or property grid. I can then take the same action that the attached property delegate did previously.

    The way I got around the morph helper issue was to send in the required value as a constructor parameter. This also seems to be more correct anyway as CLR properties are not supposed to change after the activity instance is created from what I have read.

    Thursday, September 1, 2011 5:15 AM