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

2 posts, 0 answers
  1. Art
    Art avatar
    23 posts
    Member since:
    Apr 2015

    Posted 18 Sep 2015 Link to this post

     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;
        }
    }

     

  2. Art
    Art avatar
    23 posts
    Member since:
    Apr 2015

    Posted 18 Sep 2015 Link to this post

    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).

  3. DevCraft banner
Back to Top