开发者

Binding does not have a Clone method, whats an effective way to copy it

I wish to copy a binding, this is so i ca开发者_Go百科n set a different source property on it without affecting the original binding. Is this just a case of setting all of the properties on the new binding to be the same as the old?


Here is my solution to the problem:

public static BindingBase CloneBinding(BindingBase bindingBase, object source)
{
    var binding = bindingBase as Binding;
    if (binding != null)
    {
        var result = new Binding
                         {
                             Source = source,
                             AsyncState = binding.AsyncState,
                             BindingGroupName = binding.BindingGroupName,
                             BindsDirectlyToSource = binding.BindsDirectlyToSource,
                             Converter = binding.Converter,
                             ConverterCulture = binding.ConverterCulture,
                             ConverterParameter = binding.ConverterParameter,
                             //ElementName = binding.ElementName,
                             FallbackValue = binding.FallbackValue,
                             IsAsync = binding.IsAsync,
                             Mode = binding.Mode,
                             NotifyOnSourceUpdated = binding.NotifyOnSourceUpdated,
                             NotifyOnTargetUpdated = binding.NotifyOnTargetUpdated,
                             NotifyOnValidationError = binding.NotifyOnValidationError,
                             Path = binding.Path,
                             //RelativeSource = binding.RelativeSource,
                             StringFormat = binding.StringFormat,
                             TargetNullValue = binding.TargetNullValue,
                             UpdateSourceExceptionFilter = binding.UpdateSourceExceptionFilter,
                             UpdateSourceTrigger = binding.UpdateSourceTrigger,
                             ValidatesOnDataErrors = binding.ValidatesOnDataErrors,
                             ValidatesOnExceptions = binding.ValidatesOnExceptions,
                             XPath = binding.XPath,
                         };

        foreach (var validationRule in binding.ValidationRules)
        {
            result.ValidationRules.Add(validationRule);
        }

        return result;
    }

    var multiBinding = bindingBase as MultiBinding;
    if (multiBinding != null)
    {
        var result = new MultiBinding
                         {
                             BindingGroupName = multiBinding.BindingGroupName,
                             Converter = multiBinding.Converter,
                             ConverterCulture = multiBinding.ConverterCulture,
                             ConverterParameter = multiBinding.ConverterParameter,
                             FallbackValue = multiBinding.FallbackValue,
                             Mode = multiBinding.Mode,
                             NotifyOnSourceUpdated = multiBinding.NotifyOnSourceUpdated,
                             NotifyOnTargetUpdated = multiBinding.NotifyOnTargetUpdated,
                             NotifyOnValidationError = multiBinding.NotifyOnValidationError,
                             StringFormat = multiBinding.StringFormat,
                             TargetNullValue = multiBinding.TargetNullValue,
                             UpdateSourceExceptionFilter = multiBinding.UpdateSourceExceptionFilter,
                             UpdateSourceTrigger = multiBinding.UpdateSourceTrigger,
                             ValidatesOnDataErrors = multiBinding.ValidatesOnDataErrors,
                             ValidatesOnExceptions = multiBinding.ValidatesOnDataErrors,
                         };

        foreach (var validationRule in multiBinding.ValidationRules)
        {
            result.ValidationRules.Add(validationRule);
        }

        foreach (var childBinding in multiBinding.Bindings)
        {
            result.Bindings.Add(CloneBinding(childBinding, source));
        }

        return result;
    }

    var priorityBinding = bindingBase as PriorityBinding;
    if (priorityBinding != null)
    {
        var result = new PriorityBinding
                         {
                             BindingGroupName = priorityBinding.BindingGroupName,
                             FallbackValue = priorityBinding.FallbackValue,
                             StringFormat = priorityBinding.StringFormat,
                             TargetNullValue = priorityBinding.TargetNullValue,
                         };

        foreach (var childBinding in priorityBinding.Bindings)
        {
            result.Bindings.Add(CloneBinding(childBinding, source));
        }

        return result;
    }

    throw new NotSupportedException("Failed to clone binding");
}


if you can't find a method to do this already create an exetension for Binding.

    public static class BindingExtensions
{
    public static Binding Clone(this Binding binding)
    {
        var cloned = new Binding();
        //copy properties here
        return cloned;
    }
}

public void doWork()
{
    Binding b= new Binding();
    Binding nb = b.Clone(); 
}


I just noticed in BindingBase decompiled code that it has an internal Clone() method, so another (unsafe, don't try at home, use at your own risk, etc.) solution would be to use reflection to bypass the compiler's access limitations:

public static BindingBase CloneBinding(BindingBase bindingBase, BindingMode mode = BindingMode.Default)
{
    var cloneMethodInfo = typeof(BindingBase).GetMethod("Clone", BindingFlags.Instance | BindingFlags.NonPublic);
    return (BindingBase) cloneMethodInfo.Invoke(bindingBase, new object[] { mode });
}

Didn't try it, though, so it might not work.


I just started using this. It's not the most efficient but is fast enough for me so far. It's simple and in theory shouldn't miss any properties.

using System.IO;
using System.Windows.Data;
using System.Windows.Markup;
using System.Xml;

static Binding CloneBinding(Binding binding)
{
    var xaml = XamlWriter.Save(binding);
    var stringReader = new StringReader(xaml);
    var xmlReader = XmlReader.Create(stringReader);
    return (Binding)XamlReader.Load(xmlReader);
}

Inspired by another question's answer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜