This is a migrated thread and some comments may be shown as answers.

Custom Merge Field: How to pass a new DisplayName property into the CodeFragment (instead of Property Path)?

1 Answer 39 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
Art
Top achievements
Rank 1
Art asked on 18 Sep 2015, 06:15 AM

 I'm trying to replace the Code view of PropertyPath in {MF PropertyPath} to {MF DisplayName}, which still uses PropertyPath inside.

[XamlSerializable]
public string DisplayName
{
    get { return _displayName.GetValue(); }
 
    set
    {
        if (!_displayName.IsNestedField && _displayName.GetValue() == value)
            return;
 
        _displayName.SetValue(value);
        InvalidateCode();
    }
}
 
[XamlSerializable]
public string PropertyPath
{
    get
    {
        return _propertyPath.GetValue();
    }
 
    set
    {
        if (!_propertyPath.IsNestedField && _propertyPath.GetValue() == value)
            return;
 
        _propertyPath.SetValue(value);
        InvalidateCode();
    }
}
 

 They XamlSerializable, then there should be no problems.

 But there is a problem with the implementation of CopyPropertiesFromCodeExpression.

 

protected override void CopyPropertiesFromCodeExpression(FieldCodeExpression fieldCodeExpression)
{
    if (fieldCodeExpression.FieldArgumentNode != null)
    {
        _propertyPath.SetValue(fieldCodeExpression.FieldArgumentNode);
        _displayName.SetValue(fieldCodeExpression.FieldArgumentNode);
    }
    else
    {
        PropertyPath = null;
        DisplayName = null;
    }
}

 

I get a blank page without this method. Otherwise, it tries to substitute the DisplayName in PropertyPath (???).

 Full Code:

public class EnchantedMergeField : CodeBasedField
{
    public static readonly string FieldType = "MF";
    public static readonly FieldPropertyDefinition PropertyPathProperty = new FieldPropertyDefinition("PropertyPath");
    public static readonly FieldPropertyDefinition DisplayNameProperty = new FieldPropertyDefinition("DisplayName");
 
    private readonly FieldProperty _propertyPath;
    private readonly FieldProperty _displayName;
 
    static EnchantedMergeField()
    {
        CodeBasedFieldFactory.RegisterFieldType(FieldType, () => new EnchantedMergeField());
    }
 
    public EnchantedMergeField()
    {
        _propertyPath = new FieldProperty(this, PropertyPathProperty);
        _displayName = new FieldProperty(this, DisplayNameProperty);
    }
 
    public override string FieldTypeName
    {
        get { return FieldType; }
    }
 
    public override bool HasDisplayNameFragment
    {
        get
        {
            return true;
        }
    }
 
    [XamlSerializable]
    public string DisplayName
    {
        get { return _displayName.GetValue(); }
 
        set
        {
            if (!_displayName.IsNestedField && _displayName.GetValue() == value)
                return;
 
            _displayName.SetValue(value);
            InvalidateCode();
        }
    }
 
    [XamlSerializable]
    public string PropertyPath
    {
        get
        {
            return _propertyPath.GetValue();
        }
 
        set
        {
            if (!_propertyPath.IsNestedField && _propertyPath.GetValue() == value)
                return;
 
            _propertyPath.SetValue(value);
            InvalidateCode();
        }
    }
 
    protected override void CopyPropertiesFromCodeExpression(FieldCodeExpression fieldCodeExpression)
    {
        if (fieldCodeExpression.FieldArgumentNode != null)
        {
            _propertyPath.SetValue(fieldCodeExpression.FieldArgumentNode);
            _displayName.SetValue(fieldCodeExpression.FieldArgumentNode);
        }
        else
        {
            PropertyPath = null;
            DisplayName = null;
        }
    }
 
    public override void CopyPropertiesFrom(Field fromField)
    {
        base.CopyPropertiesFrom(fromField);
 
        var mergeField = (EnchantedMergeField) fromField;
 
        _propertyPath.CopyPropertiesFrom(mergeField._propertyPath);
        _displayName.CopyPropertiesFrom(mergeField._displayName);
    }
 
    public override Field CreateInstance()
    {
        return new EnchantedMergeField();
    }
 
    private string ConvertToString(object value)
    {
        string convertedValue;
 
        if (value is string)
            convertedValue = (string) value;
        else if (value is DateTime)
            convertedValue = ((DateTime) value).ToString(DateTimeFormatting);
        else
        {
            try
            {
                convertedValue = Convert.ToDecimal(value).ToString(NumericFormatting);
            }
            catch (Exception)
            {
                convertedValue = value.ToString();
            }
        }
 
        return convertedValue;
    }
 
    protected override DocumentFragment GetResultFragment()
    {
        string value = null;
 
        if (Document != null && !string.IsNullOrEmpty(PropertyPath))
        {
            var currentItem = Document.MailMergeDataSource.CurrentItem;
 
            if (currentItem != null)
            {
                value = ConvertToString(GetNestedPropertyValue(currentItem, PropertyPath));
            }
        }
 
        return CreateFragmentFromText(value);
    }
 
    protected override void BuildCodeOverride()
    {
        CodeBuilder.SetFieldArgument(_propertyPath);
    }
 
    protected override DocumentFragment GetCodeFragment()
    {
        return CreateFragmentFromText(string.Format("{{{0} {1}}}", FieldType, DisplayName));
    }
 
    protected override DocumentFragment GetDisplayNameFragment()
    {
        return CreateFragmentFromText(string.Format(DisplayNameFragmentFormat, DisplayName));
    }
 
    private static object GetNestedPropertyValue(object value, string propertyPath)
    {
        if (value == null || string.IsNullOrEmpty(propertyPath))
            return null;
 
        var currentType = value.GetType();
        var path = propertyPath.Split('.');
 
        foreach (var propertyStep in path)
        {
            var prop = currentType.GetProperty(propertyStep);
 
            if (prop == null || value == null)
            {
                value = "#{ERROR}#";
                break;
            }
 
            value = prop.GetValue(value, null);
            currentType = prop.PropertyType;
        }
 
        return value;
    }
}

 

1 Answer, 1 is accepted

Sort by
0
Art
Top achievements
Rank 1
answered on 18 Sep 2015, 10:19 AM

Removed:

protected override DocumentFragment GetCodeFragment()
    {
        return CreateFragmentFromText(string.Format("{{{0} {1}}}", FieldType, DisplayName));
    }

Changed:

protected override void CopyPropertiesFromCodeExpression(FieldCodeExpression fieldCodeExpression)
{
    if (fieldCodeExpression.FieldArgumentNode != null)
    {
        base.CopyPropertiesFromCodeExpression(fieldCodeExpression);
        _propertyPath.SetValue(fieldCodeExpression.FieldArgumentNode);
    }
    else
    {
        PropertyPath = null;
    }
}

Now it works fine in the FieldDisplayMode.DisplayName (for editor by default). ​This implementation is needed for localization, as part of a hierarchical fields presenter for Ribbon UI with a treeview on dropdownbutton (deep nested paths of the Mail Merge Source).

Tags
RichTextBox
Asked by
Art
Top achievements
Rank 1
Answers by
Art
Top achievements
Rank 1
Share this question
or