如何在使用Calibrun.Micro viewModel-first方法时在设计器中显示ContentControl?

时间:2015-03-09 11:09:32

标签: wpf xaml mvvm caliburn.micro

我在使用ViewModel-first方法的WPF应用程序中使用Caliburn.Micro(CM)。我用命令栏和活动项目组成主视图。主viewModel设置命令栏viewModel的属性,并正确导航到活动项。

在运行时一切都很好看,问题是与设计时相关:主视图在设计器中显示为空,我找不到如何正确设置它。我设法在其他情况下工作,例如在设计时为整个Window或UserControl设置datacontext时,即当它是XAML中的根UI元素时。但是现在我无法在窗口中为子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>

我检查了一些相关的读物,但它们似乎都不适合/解决我的问题。 This question与我的基本相同,但没有答案。这引用了this other question,在我看来,它是基于View的第一种方法,以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 himselfthis CM threadthis other SO

修改
在我上一次(自动)提示后,我还尝试创建并实例化 DesignTimeMainViewModel 继承自 MainViewModel ,这会暴露出来相同的属性,并在其默认构造函数中设置 DesignTimeCommandBarViewModel 。在这种情况下,设计器代替命令栏显示经典的CM投诉:无法找到DesignTimeCommandBarViewModel的视图。 下一步是什么?

1 个答案:

答案 0 :(得分:2)

嗯,这是我找到的解决方案:我很高兴听到更好的方法或其他建议。

主机 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 具有相同的公共属性,默认情况下没有依赖关系,并且其c&#39; tor设置 CommandBar < / em>属性为 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 类使用自定义属性进行修饰,该属性只有一个必需参数,与该视图模型关联的视图的 System.Type

在引导期间,代码添加了一个新的 ViewLocator 策略,通过设置新的 ViewLocator.LocateTypeForModelType 从视图模型类型中获取视图类型。

如果标准定位器功能找不到,则新定位器功能将尝试查找视图类型。当然,它将在视图模型Type上查找自定义属性,如果找到则返回视图类型。以下是其中的要点:

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;