gpt4 book ai didi

wpf - 使用 Caliburn.Micro View 模型优先方法时如何在设计器中显示内容控件?

转载 作者:行者123 更新时间:2023-12-04 12:24:55 26 4
gpt4 key购买 nike

我在采用 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>

我已经检查了一些相关的读物,但似乎没有一个适合/解决我的问题。 This question和我的基本一样,但是没有答案。引用了 this other questioncal:View.Model 绑定(bind)来看,在我看来这是一种 View 优先的方法。

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

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

但后来我遇到了两种情况之一:

  • 如果 DesignTimeCommandBarViewModel 继承自实际的 CommandBarViewModel,那么我会遇到一些设计时与依赖注入(inject)的常见问题:默认构造函数将 null 传递给所有注入(inject)的依赖项和基本构造函数或其他东西都会产生问题。我的意思是,似乎需要付出一些努力才能为此找到解决方法,而且只是为了设计时支持

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

你对这个有什么想法吗?也许这应该通过托管 MainViewModel 的设计时版本来解决?

我检查的其他引用资料:this answer, from Rob Eisenberg himself , this CM thread , this other SO

编辑
按照我最后的(自动)提示,我也在尝试创建和实例化一个 DesignTimeMainViewModel继承自 MainViewModel,它公开了相同的内容属性并在其默认构造函数中设置 DesignTimeCommandBarViewModel。在这种情况下,设计人员在命令栏的位置显示了经典的 CM 投诉:找不到 DesignTimeCommandBarViewModel 的 View 。下一步是什么?

最佳答案

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

Host MainView XAML 指定指向 Main View 模型的设计时版本的设计时数据上下文,顺便说一下,它继承来自运行时版本 MainViewModelContentControl 项保持不变。

<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 类装饰有一个自定义属性,该属性只有一个必需参数,即与该 View 模型关联的 View 的 System.Type

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

如果标准定位器函数找不到,新定位器函数将尝试查找 View 类型。当然,它会在 View 模型类型上查找自定义属性,如果找到,那将是返回的 View 类型。这是要点:

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;

关于wpf - 使用 Caliburn.Micro View 模型优先方法时如何在设计器中显示内容控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28940537/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com