使用Calibrun.Micro viewModel-first方法时,如何在设计器中显示ContentControl? [英] How to show ContentControl in designer when using Calibrun.Micro viewModel-first approach?

查看:105
本文介绍了使用Calibrun.Micro viewModel-first方法时,如何在设计器中显示ContentControl?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Caliburn.Micro (CM) in a WPF application with ViewModel-first approach. I'm composing the main view with a command bar and an active item. Main viewModel sets the property for the command bar viewModel, and navigates to active item correctly.

所有内容在运行时看起来都很好,只是与设计时相关的问题:主视图在设计器中显示为空,我找不到如何正确设置。我设法让它在其他情况下工作,例如在设计时为整个Window或UserControl设置数据上下文时,即XAML中的根UI元素时。但是现在我无法在Window中使用子ContentPresenter UI元素。

Everything looks fine at runtime, the issue is only related to design-time: the main view shows empty in designer and I cannot find how to set it correctly. I managed to having this working in other scenarios, e.g. when setting the datacontext at design time for a whole Window or UserControl, i.e. when that's the root UI element in XAML. But now I'm not able to to this for child ContentPresenter UI elements within a Window.

这是主视图的摘录正在撰写:

<Window x:Class="...MainView" ...>
  <DockPanel ...>
    <!-- this one binds to a property of type CommandBarViewModel -->
    <ContentControl x:Name="CommandBar" ... />
    <ContentControl x:Name="ActiveItem" ... />
  </DockPanel>
</Window>

我检查了一些相关的读物,但似乎没有一个适合/解决我的问题。 这个问题基本上是和我的一样,但是没有答案。那是对另一个问题的参考,在我看来我采用了视图优先的方法,通过 cal:View.Model 绑定来判断。

I've checked a number of related reads, but none of them seems to fit/solve my issue. This question is basically the same as mine, but has no answers. That has a reference to this other question which it seems to me is going for a View-first approach, judging by the cal:View.Model bindings.

我尝试添加一个设计时上下文,如下所示(为简洁起见,未显示 fake 命名空间):

I tried adding a design-time context like the following (fake namespace not shown for brevity):

<ContentControl x:Name="CommandBar" ... 
   d:DataContext="{d:DesignInstance Type=fake:DesignTimeCommandBarViewModel, IsDesignTimeCreatable=True}" 
   cal:Bind.AtDesignTime="True"/>

但随后出现两种情况之一:

but then I incur in one of two cases:


  • 如果 DesignTimeCommandBarViewModel 继承自实际的 CommandBarViewModel ,那么我会遇到一些常见的设计时Vs依赖问题注入:默认构造函数为所有注入的依赖项传递null,而基本构造函数或其他产生问题。我的意思是,似乎需要一些工作来找到解决方法,并且仅用于设计时支持

  • if DesignTimeCommandBarViewModel inherits from the actual CommandBarViewModel, then I incur in somewhat the usual problem of design-time Vs dependency injection: the default constructor passes null for all injected dependencies, and base constructor or something else gives problem. I mean, it seems it would take some effort to find a workaround for this, and just for design-time support

如果 DesignTimeCommandBarViewModel 不能从实际的viewModel继承,那么似乎(正确地)没有实例化CommandBarView,因为现在viewModel和该视图之间不再存在任何关系。

if DesignTimeCommandBarViewModel does not inherit from the actual viewModel, then it seems that (correctly) the CommandBarView is not instantiated, as now there's no relationship anymore between the viewModel and that view.

您对此有任何想法吗?也许应该使用托管MainViewModel的设计时版本解决此问题?

Have you got any idea about this? Maybe this should be solved with a design-time version of the hosting MainViewModel?

我检查过的其他参考:此答案来自Rob Eisenberg自己此CM线程其他SO

Other references I checked: this answer, from Rob Eisenberg himself, this CM thread, this other SO

编辑

(自动)提示,我也在尝试创建和实例化 DesignTimeMainViewModel MainViewModel 继承,该方法公开了相同的属性和集合默认构造函数中的 DesignTimeCommandBarViewModel 。在这种情况下,设计人员代替了命令栏,显示了经典的CM抱怨:找不到DesignTimeCommandBarViewModel的视图。
下一步是什么?

Edit
Following my last (auto-)hint, I'm trying also creating and instantiating a DesignTimeMainViewModel, not inheriting from MainViewModel, which exposes the same properties and sets a DesignTimeCommandBarViewModel in its default constructor. In this case, in place of the command bar the designer shows the classic CM complaint: cannot find view for the DesignTimeCommandBarViewModel. What's next?

推荐答案

好吧,这是我找到的解决方案:我很高兴听到更好的方法

Well, here's the solution I found: I'd be glad to hear about better ways or other suggestions.

主机 MainView XAML指定一个设计时数据上下文,该数据上下文指向Main视图模型的设计时版本。顺便说一句,不会从运行时版本 MainViewModel 继承。 ContentControl 项保持不变。

Host MainView XAML specifies a design-time data-context pointing to a design-time version of the Main view-model which, by the way, does not inherit from the runtime version MainViewModel. ContentControl items are left untouched.

<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'tor,没有依赖项,并且其c'tor将 CommandBar 属性设置为 DesignTimeCommandBarViewModel 的新实例:

DesignTimeMainPanelViewModel has the same public properties as MainPanelViewModel, has a default c'tor without dependencies and its c'tor sets the CommandBar property to a new instance of 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

DesignTimeCommandBarViewModel class is decorated with a custom Attribute having only one required parameter, the System.Type of the view associated with that view-model.

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

During bootstrap the code adds a new ViewLocator strategy to get the view Type from the view-model Type, by setting a new ViewLocator.LocateTypeForModelType.

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

The new locator function will try to find a view Type if the standard locator function cannot find one. Granted, it will look for the custom attribute on view-model Type, and if found that would be the returned view Type. Here's the gist of that:

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;

这篇关于使用Calibrun.Micro viewModel-first方法时,如何在设计器中显示ContentControl?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆