locked
Binding to ExpressionTextBox in a custom control RRS feed

  • Question

  • I am trying to put together a custom control that will be used multiple times in a custom activity designer. I want the control to use properties with primitive types. One of these properties (a string) is then bound to an ExpressionTextBox. I am not able to successfully bind this value to the ExpressionTextBox.
    Using primitive types is not strictly a requirement, but it makes the custom control design simple. I could use any type for this property as long as it gets me over the ExpressionTextBox.Expression binding problem.
    Moving forward with the string property concept, this is what I have for the converter to take that string and bind it to the ExpressionTextBox.Expression property.
    namespace MyWorkflow.Design.Presentation
    {
      using System;
      using System.Activities;
      using System.Activities.Expressions;
      using System.Activities.Presentation.Model;
      using System.Globalization;
      using System.Windows.Data;
      using Microsoft.VisualBasic.Activities;
      internal class StringToExpressionConverter : IValueConverter
      {
        public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
        {
          // Convert value to InArgument<string>
          String itemContent = value as String;
          VisualBasicValue<String> argument = new VisualBasicValue<String>(itemContent);
          InArgument<String> inArgument = new InArgument<String>(argument);
          return inArgument;
        }
        public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture)
        {
          ModelItem modelItem = value as ModelItem;
          if (modelItem == null)
          {
            return null;
          }
          InArgument<String> inArgument = modelItem.GetCurrentValue() as InArgument<String>;
          if (inArgument == null)
          {
            return null;
          }
          Activity<String> expression = inArgument.Expression;
          Literal<String> literal = expression as Literal<String>;
          if (literal != null)
          {
            return "\"" + literal.Value + "\"";
          }
          VisualBasicValue<String> vbexpression = expression as VisualBasicValue<String>;
          if (vbexpression != null)
          {
            return vbexpression.ExpressionText;
          }
          return null;
        }
      }
    }


    I think the problem here is that the convert should be wrapping the InArgument<String> as a model item but to achieve this within a converter is not clear. 
    Any pointers?

    Sunday, August 14, 2011 10:40 AM

Answers

  • Hi Rory,

     

    I may be missing a detail in your requirements, but why not use the standard  ArgumentToExpressionConverter converter?  It is defined in System.Activities.Presentation.Converters.

    Once it is declared in your designers resources:

    <sap:ActivityDesigner.Resources>
        <ResourceDictionary>
          <sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" />
        </ResourceDictionary>
    </sap:ActivityDesigner.Resources>
    

    You can use it like this:

    <sapv:ExpressionTextBox Grid.Row="0" Grid.Column="1" Expression="{Binding ModelItem.Server,Mode=TwoWay,Converter={StaticResource ArgumentToExpressionConverter}}" OwnerActivity="{Binding Path=ModelItem}"/>
    
    This will happily convert back and forth between a Expression<T> and an [Out|In]Argument<T>

     

    • Marked as answer by Rory_Primrose Monday, August 15, 2011 3:43 AM
    Sunday, August 14, 2011 11:08 AM
  • Ok, got it fixed. As expected, using the ArgumentToExpressionConverter was the answer. The tricky bit was what data type to use as the property on the user control.

    I figured that I could just bind the property from the parent designer into the user control property using its data type. I started with defining the property as Object and hooking into the OnPropertyChanged override to output the actual type of the bound value. This turned out to be ModelItem that acts like an InArgument<String>. Using InArgument<String> was not working as it doesn't have the ModelItem magic. I then modified the dependency property on the user control to be ModelItem and it is all looking good now.

    • Marked as answer by Rory_Primrose Monday, August 15, 2011 3:44 AM
    Monday, August 15, 2011 3:43 AM

All replies

  • Hi Rory,

     

    I may be missing a detail in your requirements, but why not use the standard  ArgumentToExpressionConverter converter?  It is defined in System.Activities.Presentation.Converters.

    Once it is declared in your designers resources:

    <sap:ActivityDesigner.Resources>
        <ResourceDictionary>
          <sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" />
        </ResourceDictionary>
    </sap:ActivityDesigner.Resources>
    

    You can use it like this:

    <sapv:ExpressionTextBox Grid.Row="0" Grid.Column="1" Expression="{Binding ModelItem.Server,Mode=TwoWay,Converter={StaticResource ArgumentToExpressionConverter}}" OwnerActivity="{Binding Path=ModelItem}"/>
    
    This will happily convert back and forth between a Expression<T> and an [Out|In]Argument<T>

     

    • Marked as answer by Rory_Primrose Monday, August 15, 2011 3:43 AM
    Sunday, August 14, 2011 11:08 AM
  • Hi Frank,

    I've tried that one but the control didn't display the bound value. I change the string property to InArgument<String> and then hooked up the converter but no joy. I'll give that method another go tomorrow, perhaps I missed something.

    Cheers,

    Rory 

    Sunday, August 14, 2011 11:41 AM
  • Ok, got it fixed. As expected, using the ArgumentToExpressionConverter was the answer. The tricky bit was what data type to use as the property on the user control.

    I figured that I could just bind the property from the parent designer into the user control property using its data type. I started with defining the property as Object and hooking into the OnPropertyChanged override to output the actual type of the bound value. This turned out to be ModelItem that acts like an InArgument<String>. Using InArgument<String> was not working as it doesn't have the ModelItem magic. I then modified the dependency property on the user control to be ModelItem and it is all looking good now.

    • Marked as answer by Rory_Primrose Monday, August 15, 2011 3:44 AM
    Monday, August 15, 2011 3:43 AM