使用 Calibrun.Micro viewModel-first 方法时如何在设计器中显示 ContentControl?
How to show ContentControl in designer when using Calibrun.Micro viewModel-first approach?
我在采用 ViewModel 优先方法的 WPF 应用程序中使用 Caliburn.Micro (CM)。我正在用一个命令栏和一个活动项目组成主视图。主 viewModel 为命令栏 viewModel 设置 属性,并正确导航到活动项目。
运行时一切正常,问题仅与设计时有关:主视图在设计器中显示为空,我找不到如何正确设置它。我设法让它在其他场景中工作,例如在设计时为整个 Window 或 UserControl 设置数据上下文时,即当它是 XAML 中的根 UI 元素时。但是现在我无法对 Window.
中的子 ContentPresenter UI 元素执行此操作
这是主视图的节选我正在撰写:
<Window x:Class="...MainView" ...>
<DockPanel ...>
<!-- this one binds to a property of type CommandBarViewModel -->
<ContentControl x:Name="CommandBar" ... />
<ContentControl x:Name="ActiveItem" ... />
</DockPanel>
</Window>
我已经检查了一些相关读物,但其中 none 似乎 fit/solve 我的问题。 This question is basically the same as mine, but has no answers. That has a reference to this other question 在我看来,从 cal:View.Model
绑定来看,这是一种视图优先的方法。
我尝试添加如下所示的设计时上下文(fake
命名空间为简洁起见未显示):
<ContentControl x:Name="CommandBar" ...
d:DataContext="{d:DesignInstance Type=fake:DesignTimeCommandBarViewModel, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True"/>
但后来我遇到了两种情况之一:
如果 DesignTimeCommandBarViewModel 继承自实际的 CommandBarViewModel,那么我会遇到一些常见的设计时问题VS 依赖注入:默认构造函数为所有注入的依赖项传递 null,而基本构造函数或其他东西会产生问题。我的意思是,似乎需要一些努力才能为此找到解决方法,并且 仅用于 设计时支持
如果 DesignTimeCommandBarViewModel 没有从实际的 viewModel 继承,那么似乎(正确地)CommandBarView 没有被实例化,因为现在它们之间不再有关系viewModel 和那个视图。
你有什么想法吗?也许这应该通过托管 MainViewModel 的设计时版本来解决?
我检查的其他参考资料:this answer, from Rob Eisenberg himself, this CM thread, this other SO
编辑
根据我最后的(自动)提示,我还尝试创建和实例化一个 DesignTimeMainViewModel,not 继承自 MainViewModel,它公开相同的属性并在其默认构造函数中设置 DesignTimeCommandBarViewModel。在这种情况下,设计人员在命令栏的位置显示了经典的 CM 投诉:找不到 DesignTimeCommandBarViewModel 的视图。
接下来是什么?
好吧,这是我找到的解决方案:我很高兴听到更好的方法或其他建议。
Host MainView XAML 指定指向主视图模型的设计时版本的设计时数据上下文,顺便说一下, 不继承自运行时版本MainViewModel。 ContentControl 项保持不变。
<Window x:Class="...MainView" ...
d:DataContext="{d:DesignInstance Type=fake:DesignTimeMainPanelViewModel, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True">
<DockPanel ...>
<ContentControl x:Name="CommandBar" ... />
<ContentControl x:Name="ActiveItem" ... />
</DockPanel>
</Window>
DesignTimeMainPanelViewModel 具有与 MainPanelViewModel 相同的 public 属性,具有一个没有依赖项的默认 c'tor 及其 c' tor 将 CommandBar 属性 设置为 DesignTimeCommandBarViewModel:
的新实例
public class DesignTimeMainPanelViewModel
{
public DesignTimeMainPanelViewModel()
{
CommandBar = new DesignTimeCommandBarViewModel();
ActiveItem = ...some instance here as well...;
}
public DesignTimeCommandBarViewModel CommandBar { get; private set; }
public IScreen ActiveItem { get; private set; }
}
DesignTimeCommandBarViewModel class 装饰有一个只有一个必需参数的自定义属性,即 System.Type与该视图模型关联的视图。
在 bootstrap 期间,代码添加了一个新的 ViewLocator 策略,通过设置新的 [ 从视图模型类型获取视图类型=50=].
如果标准定位器函数找不到视图类型,新定位器函数将尝试查找视图类型。当然,它会在视图模型类型上查找自定义属性,如果找到,那将是返回的视图类型。这是要点:
Type viewType = _previousLocate(viewModelType, displayLocation, context);
if (viewType == null)
{
FakeViewAttribute fakeViewAttr = Attribute.GetCustomAttribute(viewModelType, typeof(FakeViewAttribute)) as FakeViewAttribute;
if (fakeViewAttr != null) viewType = fakeViewAttr.ViewType;
}
return viewType;
我在采用 ViewModel 优先方法的 WPF 应用程序中使用 Caliburn.Micro (CM)。我正在用一个命令栏和一个活动项目组成主视图。主 viewModel 为命令栏 viewModel 设置 属性,并正确导航到活动项目。
运行时一切正常,问题仅与设计时有关:主视图在设计器中显示为空,我找不到如何正确设置它。我设法让它在其他场景中工作,例如在设计时为整个 Window 或 UserControl 设置数据上下文时,即当它是 XAML 中的根 UI 元素时。但是现在我无法对 Window.
中的子 ContentPresenter UI 元素执行此操作这是主视图的节选我正在撰写:
<Window x:Class="...MainView" ...>
<DockPanel ...>
<!-- this one binds to a property of type CommandBarViewModel -->
<ContentControl x:Name="CommandBar" ... />
<ContentControl x:Name="ActiveItem" ... />
</DockPanel>
</Window>
我已经检查了一些相关读物,但其中 none 似乎 fit/solve 我的问题。 This question is basically the same as mine, but has no answers. That has a reference to this other question 在我看来,从 cal:View.Model
绑定来看,这是一种视图优先的方法。
我尝试添加如下所示的设计时上下文(fake
命名空间为简洁起见未显示):
<ContentControl x:Name="CommandBar" ...
d:DataContext="{d:DesignInstance Type=fake:DesignTimeCommandBarViewModel, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True"/>
但后来我遇到了两种情况之一:
如果 DesignTimeCommandBarViewModel 继承自实际的 CommandBarViewModel,那么我会遇到一些常见的设计时问题VS 依赖注入:默认构造函数为所有注入的依赖项传递 null,而基本构造函数或其他东西会产生问题。我的意思是,似乎需要一些努力才能为此找到解决方法,并且 仅用于 设计时支持
如果 DesignTimeCommandBarViewModel 没有从实际的 viewModel 继承,那么似乎(正确地)CommandBarView 没有被实例化,因为现在它们之间不再有关系viewModel 和那个视图。
你有什么想法吗?也许这应该通过托管 MainViewModel 的设计时版本来解决?
我检查的其他参考资料:this answer, from Rob Eisenberg himself, this CM thread, this other SO
编辑
根据我最后的(自动)提示,我还尝试创建和实例化一个 DesignTimeMainViewModel,not 继承自 MainViewModel,它公开相同的属性并在其默认构造函数中设置 DesignTimeCommandBarViewModel。在这种情况下,设计人员在命令栏的位置显示了经典的 CM 投诉:找不到 DesignTimeCommandBarViewModel 的视图。
接下来是什么?
好吧,这是我找到的解决方案:我很高兴听到更好的方法或其他建议。
Host MainView XAML 指定指向主视图模型的设计时版本的设计时数据上下文,顺便说一下, 不继承自运行时版本MainViewModel。 ContentControl 项保持不变。
<Window x:Class="...MainView" ...
d:DataContext="{d:DesignInstance Type=fake:DesignTimeMainPanelViewModel, IsDesignTimeCreatable=True}"
cal:Bind.AtDesignTime="True">
<DockPanel ...>
<ContentControl x:Name="CommandBar" ... />
<ContentControl x:Name="ActiveItem" ... />
</DockPanel>
</Window>
DesignTimeMainPanelViewModel 具有与 MainPanelViewModel 相同的 public 属性,具有一个没有依赖项的默认 c'tor 及其 c' tor 将 CommandBar 属性 设置为 DesignTimeCommandBarViewModel:
的新实例public class DesignTimeMainPanelViewModel
{
public DesignTimeMainPanelViewModel()
{
CommandBar = new DesignTimeCommandBarViewModel();
ActiveItem = ...some instance here as well...;
}
public DesignTimeCommandBarViewModel CommandBar { get; private set; }
public IScreen ActiveItem { get; private set; }
}
DesignTimeCommandBarViewModel class 装饰有一个只有一个必需参数的自定义属性,即 System.Type与该视图模型关联的视图。
在 bootstrap 期间,代码添加了一个新的 ViewLocator 策略,通过设置新的 [ 从视图模型类型获取视图类型=50=].
如果标准定位器函数找不到视图类型,新定位器函数将尝试查找视图类型。当然,它会在视图模型类型上查找自定义属性,如果找到,那将是返回的视图类型。这是要点:
Type viewType = _previousLocate(viewModelType, displayLocation, context);
if (viewType == null)
{
FakeViewAttribute fakeViewAttr = Attribute.GetCustomAttribute(viewModelType, typeof(FakeViewAttribute)) as FakeViewAttribute;
if (fakeViewAttr != null) viewType = fakeViewAttr.ViewType;
}
return viewType;