In the completed Avalonia tutorial Todo application --- where and how do TodoListView and AddItemView acquire their DataContexts to be equal to TodoListViewModel and AddItemViewModel respectively ???
I mean their parent control MainWindow's DataContext is a MainWindowViewModel instance (as assigned in App.xaml.cs file) --- while MainWindow's Content attribute is bound to MainWindowViewModel's Content property (which does get assigned instances of the viewmodels during execution). I just cannot trace the source wherefrom TodoListView and AddItemView acquire their DataContexts. Do they get it while:
public IControl Build(object data)
{
var name = data.GetType().FullName.Replace("ViewModel", "View");
var type = Type.GetType(name);
if (type != null)
{
var viewInstance = (Control)Activator.CreateInstance(type);
// the following always evaluates to true --- i.e. DataContext is always NULL before viewInstance is returned.
if(viewInstance.DataContext == null)
Console.WriteLine($"DataContext property of the newly created View instance of {name} in ViewLocator is NULL just before returning! ");
return viewInstance ;
}
else
{
return new TextBlock { Text = "Not Found: " + name };
}
}
In short , I am unclear about where the Views generated at runtime via ViewLocator are getting their DataContext properties assigned.
Summarizing what I understood from the answer and some search and play:
If a ContentControl's (in this case Window's) Content property is a Control then the Control simply inherits the DataContext from the parent ContentControl. But if the ContentControl's Content property is a non-Control then the ContentPresenter of the ContentControl first finds a data template for the non-Control so that a child View can be generated and then sets its own DataContext to the non-Control. This newly assigned DataContext then gets inherited by the newly generated child View. Phewwwwww!
DataContext
is inherited from ContentPresenter
which is asking IDataTemplate.Build
for a new view instance. When Content
isn't a control, ContentPresenter
sets its own DataContext
to the value of Content
which gets inherited by the child view.
ContentPresenter
is used internally by the Window
to display its Content
property.
Same happens with ListBox
items.