I've came across an interesting issue for which I've found no explanation yet...
Given the very simple MVVM WPF application below, why is the list bound to the combo box only if its visibility in the ViewModel is set to public
?
Changing the TestList
visibility to internal
raises no error or warning at compile time but leaves the combo box empty at run time.
Quoting the official documentation: internal
types or members are accessible only within files in the same assembly.
And this issue is happening despite the fact that the View and the ViewModel are defined in the same assembly.
Here is how the code looks like:
Model:
class TestModel
{
internal List<string> Musketeers { get; private set; }
public TestModel()
{
Musketeers = new List<string> { "Athos", "Porthos", "Aramis" };
}
}
View:
<Window x:Class="TestWpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ComboBox Width="250" Height="25" ItemsSource="{Binding TestList}" />
</Grid>
</Window>
ViewModel:
class TestViewModel : INotifyPropertyChanged
{
TestModel myModel = new TestModel();
public List<string> TestList
{
get
{
return myModel.Musketeers;
}
}
// INotifyPropertyChanged members are below ...
}
Apart from using the name ViewModel (which itself is confusing if the class is full of logic), the one iron-clad rule of MVVM architecture is that you may never reference a View, from ViewModel.
The ViewModel is a model for the View of the app: an abstraction of the View. The ViewModel retrieves the necessary data from the DataModel, applies the UI logic and then exposes relevant data for the View to consume.
The ViewModel is essential when you want a separation of concerns between your DomainModel (DataModel) and the rest of your code.
Just create a new folder called ViewModels inside your project. So that along with the Views, Controllers and Models folders, you'll also have ViewModels. Like you already said, you talk to your DAL using your models and you talk to your views using your view models.
ViewModel
with internal
access is visible for View
, but is not visible to Binding
class, which really makes the binding work.
{Binding TestList}
is transformed into Binding
class instance, which has no knowledge about internal
members of your ViewModel
class.
This is because Data Binding uses reflection and that in turn adhers to the visibility of items. Since data binding is implemented outside of your assembly - inside the WPF libraries - it cannot see non-public members.
Binding to a non-existing member will not issue a runtime error but rather a debug output with a message containing details about the missing member.
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