Are there any data binding frameworks (BCL or otherwise) that allow binding between any two CLR properties that implement INotifyPropertyChanged
and INotifyCollectionChanged
? It seems to be it should be possible to do something like this:
var binding = new Binding();
binding.Source = someSourceObject;
binding.SourcePath = "Customer.Name";
binding.Target = someTargetObject;
binding.TargetPath = "Client.Name";
BindingManager.Bind(binding);
Where someSourceObject
and someTargetObject
are just POCOs that implement INotifyPropertyChanged
. However, I am unaware of any BCL support for this, and am not sure if there are existing frameworks that permit this.
UPDATE: Given that there is no existing library available, I have taken it upon myself to write my own. It is available here.
Thanks
I wrote Truss to fill the void.
I'm not aware of any library that does this - but you could write your own fairly easily.
Here's a basis I knocked up in a few minutes that establishes two way data binding between two simple properties:
public static class Binder
{
public static void Bind(
INotifyPropertyChanged source,
string sourcePropertyName,
INotifyPropertyChanged target,
string targetPropertyName)
{
var sourceProperty
= source.GetType().GetProperty(sourcePropertyName);
var targetProperty
= target.GetType().GetProperty(targetPropertyName);
source.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
targetProperty.SetValue(target, sourceValue, null);
}
};
target.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
sourceProperty.SetValue(source, targetValue, null);
}
};
}
}
Of course, this code lacks a few niceties. Things to add include
source
and target
are assignedsourcePropertyName
and targetPropertyName
existAlso, Reflection is relatively slow (though benchmark it before discarding it, it's not that slow), so you might want to use compiled expressions instead.
Lastly, given that specifying properties by string is error prone, you could use Linq expressions and extension methods instead. Then instead of writing
Binder.Bind( source, "Name", target, "Name")
you could write
source.Bind( Name => target.Name);
AutoMapper can copy values between two instances, but you have to write your own code to make this happen automatically.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With