0

在完成的 Avalonia 教程 Todo 应用程序中 --- TodoListView 和 AddItemView 在哪里以及如何获取它们的 DataContexts 以分别等于 TodoListViewModel 和 AddItemViewModel ???
我的意思是他们的父控件 MainWindow 的 DataContext 是一个 MainWindowViewModel 实例(在 App.xaml.cs 文件中分配)---而 MainWindow 的 Content 属性绑定到 MainWindowViewModel 的 Content 属性(在执行期间它确实获得了视图模型的分配实例)。我只是无法追踪 TodoListView 和 AddItemView 获取其 DataContexts 的来源。他们是否在以下情况下得到它:

  1. 由 ViewLocator 在运行时创建?-- 但这是不可能的,因为在 ViewLocator 返回 View 实例之前,新实例化的 View 的 DataContext 属性仍然为 NULL -- 如已完成应用程序中以下代码的输出所示(if 块中的代码由我产生所需的输出):
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 };
            }
        }
  1. 或者他们得到父 Window 分配的 DataContext ?--- 但是父窗口自己的 DataContext 是 MainWindowViewModel ----- 我们如何从 MainWindowViewModel 到 TodoListViewModel 或 AddItemViewModel ???

简而言之,我不清楚在运行时通过 ViewLocator 生成的视图在哪里分配了它们的 DataContext 属性。


总结一下我从答案和一些搜索和游戏中理解的内容:


如果 ContentControl(在本例中为 Window)的 Content 属性是 Control,则 Control 只需从父 ContentControl 继承 DataContext。但是如果ContentControl的Content属性是non-Control,那么ContentControl的ContentPresenter首先会为non-Control找到一个数据模板,这样就可以生成一个子View,然后将自己的DataContext设置为non-Control。这个新分配的 DataContext 然后被新生成的子 View 继承。呸呸呸!

4

1 回答 1

2

DataContext继承自ContentPresenter它要求IDataTemplate.Build一个新的视图实例。当Content不是一个控件时,ContentPresenter 将它自己 DataContext的值设置Content为子视图继承的值。

ContentPresenter内部使用Window以显示其Content属性。

物品ListBox也是如此。

于 2020-04-30T10:48:41.213 回答