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
