I wish to copy a binding, this is so i can 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?
Asked
Active
Viewed 7,129 times
12
-
1I have now found that I don't need to copy a binding, in code I can use a binding more than once on different elements. – Aran Mulholland Jun 15 '11 at 02:06
4 Answers
14
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");
}
-
Why are ElementName and RelativeSource commented out? I'm guessing you encountered an issue when trying to clone those properties? – Steve Cadwallader Mar 02 '11 at 15:17
-
2Binding only allows you to set one of ElementName, RelativeSource or Source. If you try to set more than one, it throws an InvalidOperationException. – Samuel Jack Apr 04 '11 at 14:25
-
2I was having trouble using the above, except I was copying the source from the old binding to the new. In my case the binding inherits the DataContext as its source. When I copy source, it explicitly sets null as the source which apparently causes the DataContext not to be used. To overcome this, use: 'Source = binding.Source ?? DependencyProperty.UnsetValue; – xr280xr Mar 22 '12 at 15:18
-
1
2
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();
}

gingerbreadboy
- 7,386
- 5
- 36
- 62
1
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.

splintor
- 9,924
- 6
- 74
- 89
-
1Worked for me!! With the caveat that the binding is cloned *including* the private _isSealed field. I needed to set NotifyOnTargetUpdated to true (on an existing binding), which is not possible after the binding has been used somewhere. Instead, I cloned it, reset the _isSealed field, set NotifyOnTargetUpdated and then set this binding back to the original DependencyObject (replacing the original). – Tomas Karban Oct 26 '21 at 17:02
0
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.

Vimes
- 10,577
- 17
- 66
- 86