15
votes

I am trying some different things using MVVM. In our ViewModel properties which are bind to View are public. I am taking example of a button binding. Here is a simple sample.

View.xaml:

<Button Content="Test Button" Command="{Binding TestButtonCommand}" />

ViewModel.cs

private ICommand _testButtonCommand;
public ICommand TestButtonCommand
{
    get { return _testButtonCommand?? (_testButtonCommand= new RelayCommand(SomeMethod)); }
}

Here my question is that can we make TestButtonCommand internal instead of public? Internal means it is accessible to current project so their should not be any problem doing that? But when I tried to do that it didn't worked. Adding a breakpoint in getter was not hit. So why we cannot make it internal?

Here is the link from msdn.

http://msdn.microsoft.com/en-us/library/ms743643.aspx

The properties you use as binding source properties for a binding must be public properties of your class. Explicitly defined interface properties cannot be accessed for binding purposes, nor can protected, private, internal, or virtual properties that have no base implementation.

Why we cannot do this?

In case of access internal is same as public if working in the same project. Then why we cannot use internal here? There must be a reason that these should be public, and I am looking for that reason.

internal ICommand TestButtonCommand { ...... }
7
Because you can only bind to public properties, sub-properties and indexers or any CLR object. Why the WPF team went with such design decision? I don't know, you should ask them :) - Patryk Ćwiek
Its Microsoft, so we cannot do anything, - fhnaseer

7 Answers

26
votes

In case of access internal is same as public if working in the same project. Then why we cannot use internal here. There must be a reason that these should be public, and I am looking for that reason.

You have part of your answer in your question itself in the quote from Microsoft:

The properties you use as binding source properties for a binding must be public properties of your class.

Presumably / speculatively, the reason for this is that internals can only be accessed within the same assembly and not from outside. Binding to internals doesn't work because binding is resolved by the WPF binding engine which is in a separate assembly PresentationFramework.dll.

11
votes

Binding is only supported for public properties. MSDN reference:

http://msdn.microsoft.com/en-us/library/ms743643.aspx

As quoted in the reference

The properties you use as binding source properties for a binding must be public properties of your class. Explicitly defined interface properties cannot be accessed for binding purposes, nor can protected, private, internal, or virtual properties that have no base implementation.

2
votes

The internal visibility is really only meaningful to the compiler and the IL verifier, because they know the full context of the member access; the WPF binding engine does not. It knows that a binding exists on a property; it has no idea who set the property. It could have been set in the XAML, or dynamically at runtime (technically, even if you set it in the XAML, it is still applied dynamically).

Since there is no way to enforce the access rules, allowing binding to internal properties would be equivalent to allowing binding to private properties, not public properties.

2
votes

Obviously, it depends on what you're trying to achieve from this situation - you don't state what the overall aim is. I have just come across a similar problem with my code, and also happened upon a solution for my case. One of my libraries contains helper objects with various properties, but when these are used in the application project, I only want to see the properties that are of any use to me - I wanted to hide, for example, the Command properties.

My solution to hide them from the 'user' of the library is to add the

<EditorBrowsable(EditorBrowsableState.Never)>

attribute to each property that bears little or no interest to me.

Hope that helps someone!

1
votes

From http://msdn.microsoft.com/en-us/library/ms743643.aspx

For CLR properties, data binding works as long as the binding engine is able to access the binding source property using reflection. Otherwise, the binding engine issues a warning that the property cannot be found and uses the fallback value or the default value, if it is available.

0
votes

Created internal property are breaking good OO design and are breaking encapsulation. You can use internal set accessor (and public get accessor) for your case.

public ICommand SaveCommand
{
    get;
    internal set;
}

If you have a field encapsulated into a property, you should make it a rule to always access that field throught a property even inside your class. It's best practise.

0
votes

It is not possible to bind to internal properties. You can make your class as internal though, if you do not want your class to be accessible outside the project.