Non-public Data Binding sources

The short story:

Have you ever tried to use any non-public property as source to a data binding?

The long story:

We are used to generate pairs of properties as binding source: One private back-property and one public property to be actually referenced. In multi-platform projects with the Models and Viewmodels residing in a platform-independent Portable Class Library, it’s clear that these properties must actually be marked public in order to be visible to the View that is typically defined in a separate, platformspecific assembly.

However, when targeting only one platform and defining all code parts within the same project, it should be sufficient to use internal properties, since they are only referenced from within the same assembly? Well, as a simple example proves (and as MSDN states), this is not true – binding sources must be public properties. Confusingly enough, when binding to a non-public property, the binding will silently fail and deliver nothing to its target, without throwing any errors.

From a technical point of view, the common logic of private properties being visible only within the defining class and all others outside of this class does not apply here, since bindings are resolved at runtime using complex reflection logic. Reflection generally works the other way round, as you can easily try on your own: The reflection method GetProperties() returns only public properties, only when specifying the BindingFlags.NonPublic parameter, internal, protected and private members are included. So, theoretically it should be possible for the algorithm that resolves the binding to find even non-public properties, but I suspect Microsoft made the decision of allowing only public binding sources deliberately.

Lessons learned:

Anyway, what we need to do is always declare binding sources as public. This won’t be difficult to remember for plain properties as well as commands, it applies also to resx resource files to be referenced within XAML code: In this case, the resource file’s access modifier needs to be set to Public instead of Internal.