I love WPF

"jamais sans son interface"

I love WPF

"jamais sans son interface"

Clone visual tree with binding

here a class for clonning visualtree inside with binding

 public class Header : ContentControl, ICloneable
    {
        static Header()
        {
            EditorHelper.Register<BindingExpression, BindingConvertor>();
        }

        public object Clone()
        {
            StringBuilder outstr = new StringBuilder();
            //this code need for right XML fomating 
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.OmitXmlDeclaration = true;
            XamlDesignerSerializationManager dsm = new XamlDesignerSerializationManager(XmlWriter.Create(outstr, settings));
            //this string need for turning on expression saving mode 
            dsm.XamlWriterMode = XamlWriterMode.Expression;
            XamlWriter.Save(this, dsm);

            // recreate from stringbuilder
            StringReader stringReader = new StringReader(outstr.ToString());
            System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(stringReader);
            object newObj = System.Windows.Markup.XamlReader.Load(xmlReader);
            if(newObj is Header)
            {
                Header h = newObj as Header;
                h.DataContext = this.DataContext;
            }
            return newObj;
        }
    }

    static class EditorHelper
    {
        public static void Register<T, TC>()
        {
            Attribute[] attr = new Attribute[1];
            TypeConverterAttribute vConv = new TypeConverterAttribute(typeof(TC));
            attr[0] = vConv;
            TypeDescriptor.AddAttributes(typeof(T), attr);
        }
    }

    class BindingConvertor : ExpressionConverter
    {
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(MarkupExtension))
                return true;
            else return false;
        }
        public override object ConvertTo(ITypeDescriptorContext context,
                                         System.Globalization.CultureInfo culture,
                                         object value, Type destinationType)
        {
            if (destinationType == typeof(MarkupExtension))
            {
                BindingExpression bindingExpression = value as BindingExpression;
                if (bindingExpression == null)
                    throw new Exception();
                return bindingExpression.ParentBinding;
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

and use like this

<local:Header>
      <StackPanel Orientation="Horizontal">
           <Ellipse Height="16"
                    Width="16"
                    Fill="Red" />
           <TextBlock Text="{Binding Nom}" />
      </StackPanel>
</local:Header>

Principes

  • create a binding converter
  • register converter for binding
  • save xaml with settings and reload it
  • set the same datacontext for source and clonning object

you must check if the datacontext of Header object is the real DataContext of object inside in visual tree

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Retour en haut