Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 绑定没有克隆方法,复制它的有效方法是什么_C#_Wpf_Data Binding_Clone - Fatal编程技术网

C# 绑定没有克隆方法,复制它的有效方法是什么

C# 绑定没有克隆方法,复制它的有效方法是什么,c#,wpf,data-binding,clone,C#,Wpf,Data Binding,Clone,我希望复制一个绑定,这样我就可以在不影响原始绑定的情况下对其设置不同的源属性。这只是将新绑定上的所有属性设置为与旧绑定相同的情况吗?如果找不到执行此操作的方法,则已为绑定创建一个exetension public static class BindingExtensions { public static Binding Clone(this Binding binding) { var cloned = new Binding(); //

我希望复制一个绑定,这样我就可以在不影响原始绑定的情况下对其设置不同的源属性。这只是将新绑定上的所有属性设置为与旧绑定相同的情况吗?

如果找不到执行此操作的方法,则已为绑定创建一个exetension

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

以下是我对这个问题的解决方案:

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

我刚刚注意到BindingBase反编译代码中有一个内部的
Clone()
方法,所以另一个(不安全、不要在家尝试、使用风险自负等)解决方案是使用反射绕过编译器的访问限制:

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

不过,我没有试过,所以它可能不起作用。

我刚开始使用它。这不是最有效的,但对我来说已经足够快了。它很简单,理论上不应该遗漏任何属性

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

受另一个问题启发。

为什么ElementName和RelativeSource被注释掉了?我猜您在尝试克隆这些属性时遇到了问题?绑定只允许您设置ElementName、RelativeSource或Source中的一个。如果您尝试设置多个绑定,它会抛出InvalidOperationException。我在使用上述绑定时遇到了问题,只是我正在将源代码从旧绑定复制到新绑定。在我的例子中,绑定继承DataContext作为其源。当我复制源代码时,它显式地将null设置为源代码,这显然会导致不使用DataContext。要克服这个问题,请使用:“Source=binding.Source??DependencyProperty.Value;谢谢,你帮我省了一个小时!我现在发现我不需要复制绑定,在代码中我可以在不同的元素上多次使用绑定。