Technically, how does data binding engines work under the hood? Especially, how does the mechanism of the “synchroniser” in data binding look like and work like?
In many frameworks like in .NET, Java, Flex, etc, they provide a data binding engine. I have been just using the API calls, and so every thing is easy for me since all I have to do was to make calls to the API.
Now, I am interested in perhaps trying to write a relatively simple data binding engine for a game that I am working on. Although I’m using C#, I have reasons for not being able to use the built-in WinForms and data binding engine (see background info below for reason). Since I can’t use the existing data binding engine in C#, I thought I may have to write one on my own. So, I need to know the nitty gritty details of how data binding usually works under the hood. By this, I don’t mean how to use data binding in C#. I mean, how does the data binding work internally and architecturally.
I tried to search the web for tutorials and articles on data binding but most of the results came to me as being how to use the existing data binding in C#, which isn’t what I want.
So, before I could start planning on writing my own data binder, I thought I would need to know how does data binding engines work under the hood? And even more importantly, how does the mechanism of the “synchroniser” in data binding engine look and work like, ie, how are the data kept synchronised all the time be it in a one-way or two-way binding?
Some bit of background information of why I asked this question:
A while ago, I made a question on how I could use data binding in C# for UIs that are not using the standard WinForms. The answer I got was that the data binding engine in C# is tightly coupled with the WPF/Windows Forms UI. So, I guess I cannot use the existing data binding engine in C#, and have to probably create one on my own. The purpose of this is for a game and I’m working on. Games usually have its own custom UI (non-WinForm). My intention is to setup a MVVM-like design for the UI and gameobjects within the game.
Your question is a really interesting one, but it’s scope is actually very large.
A really useful tool in these situation is ILSpy which allows you to look at the framework implementations.
One thing I would take issue with is the following statement:
I disagree; the data binding engine is tightly coupled to the .Net eventing implementation, but the Target and Source can be anything – most examples will be Windows Forms, WPF or ASP.Net because they are the most common front ends for .Net languages, but it’s perfectly possible to use multi binding in other scenarios without a UI too.
What happens when you add a two way binding? Well, if we look at the source for MultiBinding we note a few interesting things:
OneWayorTwoWayNotifyOnSourceUpdatedandNotifyOnTargetUpdatedWhich have the basic form:
i.e. we use events to tell us when the source is updated (
OneWay) and when the target is updated too (forTwoWaybinding)Note there is also a
PriorityBindingclass which operates in a similar way except you can subscribe to multiple data sources, and it will prioritize the one that returns data soonest.So the shape of how this works is clear – when we create a binding, we are subscribing to changes on one side (for read only updates) or on both sides (when the data can be changed in the GUI for example, and sent back to the data source), with all notifications managed via eventing.
The next question is, really, who manages the events? The simple answer is that both the Target and Source do. That’s why implementing
INotifyPropertyChangedis important, for example – all the Bindings really do is create a contract for how both sides should subscribe to each other’s changes – it’s the contract the Target and Source are tightly coupled to, really.ObservableCollection is an interesting test case to study as it’s widely used in GUI applications for promoting updates in the data source to the UI, and for sending changes to the data in the UI back to the underlying data source.
Notice (by looking at the code) how the actual eventing for communicating that things have changed is really simple, BUT the code for managing Adds, Removes, Updates is actually very dependent on consistency via the SimpleMonitor property (
BlockReentrancyandCheckReentrancy) – it’s effectively guaranteeing that the operations are atomic and that subscribers are notified of the changes in the order they happen AND that the underlying collection is consistent with those updated.This really is the tricky part of the whole operation.
In short, the DataBinding implementation in .Net is not tightly coupled to the GUI technologies; it’s just that most examples will present DataBinding in the context of Windows Forms, WPF or ASP.Net applications. The actual databinding is event driven, and, for you to leverage it, it is more important to synchronize and manage the changes to your data – the DataBinding framework will just allow you to couple Target and Source together in shared data updates via the contract (Interfaces) it defines.
Have fun 😉
EDIT:
I sat down and created two classes,
MyCharacterandMyCharacterAttributewith the express aim of setting up TwoWay databinding between theHealthandHealthValueattributes:The most important things to note here are the inheritance from DependencyObject and the implementation of the DependencyProperty.
In practice, then, what happens is the following. I created a simple WPF form and set up the following code:
Clicking the HitCharacter button decreases the
CharacterAttributes.HealthValueproperty by 10. This fires an event, which, via the Binding we set up earlier, also subtracts 10.0 from theCharacter.Healthvalue. Hitting the DrinkHealth button restoresCharacter.Healthby 20.0 and also increases theCharacterAttributes.HealthValueby 20.0.Also note that this stuff is indeed baked into the UI framework –
FrameworkElement(which inherits fromUIElement) hasSetBindingandGetBindingimplemented on it. Which makes sense – DataBinding GUI elements is a perfectly valid scenario for user interfaces! If you look deeper, though,SetValue, for example, is just callingBindingOperations.SetBindingon an internal interface, so we can implement it without actually having to use aUIElement(as per the example above). The one dependency we have to carry over, however, isDependencyObjectandDependencyProperty– these are mandatory for the DataBinding to work, but, as long as your objects inherit fromDependencyObject, you don’t need to go anywhere near a text box 🙂The downside, however, is that some of the Binding stuff has been implemented via
internalmethods, so you may encounter scenarios where the binding actions you want to implement may require you to write additional code because you simply can’t access the framework implementations like native classes can. However, TwoWay databinding like the example above is perfectly possible, as has been shown.