2009-12-16 5 views
9

Ich möchte eine Bindung kopieren, das ist so kann ich eine andere Source-Eigenschaft darauf festlegen, ohne die ursprüngliche Bindung zu beeinträchtigen. Ist das nur der Fall, wenn alle Eigenschaften der neuen Bindung so festgelegt werden, dass sie mit denen der alten identisch sind?Binding hat keine Clone-Methode, was ist eine effektive Möglichkeit, es zu kopieren

+1

Ich habe jetzt festgestellt, dass ich keine Bindung kopieren muss, in Code kann ich eine Bindung mehr als einmal auf verschiedenen Elementen verwenden. –

Antwort

2

Wenn Sie eine Methode dazu nicht finden können, erstellen Sie bereits eine Erweiterung für 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

ich denke, ich muss nur diese Eigenschaften manuell kopieren, dann ... –

13

Hier ist meine Lösung für das 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"); 
} 
+0

Warum sind ElementName und RelativeSource auskommentiert? Ich vermute, dass Sie beim Versuch, diese Eigenschaften zu klonen, auf ein Problem gestoßen sind. –

+2

Nur Bindung ermöglicht Ihnen das Festlegen von ElementName, RelativeSource oder Source. Wenn Sie versuchen, mehrere Werte festzulegen, wird eine InvalidOperationException ausgelöst. –

+2

Ich hatte Probleme mit dem oben genannten, außer dass ich die Quelle von der alten Bindung an die neue bin. In meinem Fall erbt die Bindung den DataContext als Quelle. Wenn ich Quelle kopiere, setzt sie explizit null als die Quelle, die anscheinend den DataContext nicht benutzt. Um dies zu umgehen, verwenden Sie: 'Source = binding.Source ?? DependencyProperty.UnsetValue; – xr280xr

0

ich in Binding habe gerade bemerkt dekompilierten Code, der es eine interne Clone() Methode hat, so eine andere (nicht sicher, versuchen Sie nicht zu Hause, verwenden auf eigene Gefahr, etc.) Lösung wäre Reflektion zu verwenden, um die Compiler Zugangsbeschränkungen zu umgehen:

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

Hat es nicht versuchen, obwohl, so könnte es nicht funktionieren.