2009-12-16 50 views
9

我希望复制一个绑定,这是因为我可以在其上设置不同的源属性而不影响原始绑定。这只是将新绑定的所有属性设置为与旧相同的情况?绑定没有克隆方法,什么是复制它的有效方法

+1

我现在发现我不需要复制绑定,在代码中,我可以在不同的元素上多次使用绑定。 – 2011-06-15 02:06:29

回答

2

如果你找不到一个方法来做到这一点,已经为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(); 
} 
+0

我想我只需要手动复制这些属性然后... – 2010-01-13 00:43:55

13

这里是我的问题的解决方案:

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

为什么ElementName和RelativeSource被注释掉了?我猜你在克隆这些属性时遇到了问题? – 2011-03-02 15:17:51

+2

绑定仅允许您设置ElementName,RelativeSource或Source之一。如果您尝试设置多个,则会引发InvalidOperationException。 – 2011-04-04 14:25:17

+2

我在使用上述时遇到了问题,除了我将源代码从旧的绑定复制到新的。在我的情况下,绑定继承DataContext作为其源。当我复制源时,它明确地将null设置为显然不会使用DataContext的源。要解决这个问题,请使用:'Source = binding.Source ?? DependencyProperty.UnsetValue; – xr280xr 2012-03-22 15:18:14

0

我只注意到在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 }); 
} 

没有尝试,虽然如此,它可能无法正常工作。

相关问题