2009-12-16 7 views
9

Desidero copiare un'associazione, in questo modo posso impostare una diversa proprietà di origine su di essa senza influire sul binding originale. È solo un caso di impostare tutte le proprietà sul nuovo binding per essere uguali al vecchio?Binding non ha un metodo Clone, qual è un modo efficace per copiarlo

+1

Ora ho trovato che non è necessario copiare un'associazione, nel codice posso utilizzare un'associazione più di una volta su diversi elementi. –

risposta

2

se non riesci a trovare un metodo per farlo, crea già un'espressione per 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

Immagino di dover semplicemente copiare manualmente queste proprietà ... –

13

Qui è la mia soluzione al problema:

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

Perché ElementName e RelativeSource sono commentati? Immagino che tu abbia riscontrato un problema durante il tentativo di clonare quelle proprietà? –

+2

Il binding consente solo di impostare ElementName, RelativeSource o Source. Se si tenta di impostarne più di uno, viene generata un'eccezione InvalidOperationException. –

+2

Si è verificato un problema nell'utilizzo di quanto sopra, ad eccezione del fatto che stavo copiando la sorgente dal vecchio binding al nuovo. Nel mio caso l'associazione eredita DataContext come sua fonte. Quando copio il codice sorgente, imposta in modo esplicito null come origine che apparentemente non utilizza DataContext. Per superare questo, utilizzare: 'Source = binding.Source ?? DependencyProperty.UnsetValue; – xr280xr

0

ho appena notato in BindingBase decompilato codice che ha un metodo interno Clone(), quindi un altro (non sicuro, non provare a casa, l'uso a proprio rischio, ecc) soluzione sarebbe quella di utilizzare la reflection per bypassare le limitazioni di accesso del compilatore:

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

non provate, però, quindi potrebbe non funzionare.

Problemi correlati