问题 我能以某种方式告诉Resharper有关ViewModel的类型吗?


我们在不同的程序集中有Views和ViewModel。视图的程序集具有对VM的引用。 (有时我们需要代码)。

ViewModel的DataContext是在代码中设置的,而不是在XAML中。因此,VS和Resharper都不能提供帮助,因为intellisense和Resharper也提供了很多警告。

是否有任何针对Resharper的指令我们可以在XAML注释中设置我们打算使用View与特定类型的VM?

更新:

尼斯 博文 作为已接受答案的补充。


12654
2017-12-13 15:28


起源

不幸的是,当Resharper置于代码隐藏中时,它将不会(也将无法)解析ViewModel。这种方法的唯一方法是将它放在XAML中的UIElement的.DataContext属性中。将它置于代码隐藏中的理由是什么?也许我可以进一步提供帮助? - Patrick McCurley
我们对VM使用构造函数依赖注入。虚拟机可以通过VmManager相互访问。我们更喜欢VM有权决定导航的工作方式。视图根本没有转换只是绑定到命令和属性。我们使用codebehind来调整fokus行为或输入。 - Pavel Voronin


答案:


我遇到了同样的问题并通过使用XAML中的设计时支持来解决它,以便在XAML编辑器中获得智能感知支持,该编辑器也满足Resharper绑定验证。

请注意下面的代码段中使用的d:名称空间。这将在运行时被忽略。您还可以使用ViewModelLocator,它将设计时(Fake)存储库添加到IoC容器中,从Web服务或其他数据源等外部源中删除任何依赖项。

XAML设计时间支持:

<local:ViewBase
    ...
    mc:Ignorable="d" 
    d:DataContext="{Binding Source={d:DesignInstance Type=viewModel:MainViewModel, IsDesignTimeCreatable=True}}">

XAML ViewModelLocator:

<local:ViewBase
    ...
    mc:Ignorable="d" 
    viewModel:ViewModelLocator.ViewModel="MainViewModel" >

ViewModelLocator:

    static ViewModelLocator()
    {
        if (DesignMode.DesignModeEnabled)
        {
            Container.RegisterType<IYourRepository, YourDesignTimeRepository>();
        }
        else
        {
            Container.RegisterType<IYourRepository, YourRuntimeRepository>();
        }

        Container.RegisterType<YourViewModel>();
    }

10
2017-12-30 10:51



到目前为止最好的答案! - Telemat
“名称空间前缀”mc“未定义” - Den


如果将ViewModel设置为XAML中UIElement的.DataContext属性作为占位符,则在运行时通过构造函数注入的ViewModel将其替换。

所以你可以拥有

<UserControl.DataContext>
    <Pages:WelcomeLoadingViewModel />
</UserControl.DataContext>

然后在UserControls构造函数中有

public WelcomeLoading(WelcomeLoadingViewModel viewModel)
{
   this.DataContext = viewModel;
}

要么

public HomePage()
{
   this.InitializeComponent();

   this.DataContext = ViewModelResolver.Resolve<HomePageViewModel>();

这意味着您将获得Binding和Resharper支持,因为它们可以反映XAML Datacontext中的ViewModel。但也享受Dependancy Injected ViewModels的好处,因为VM将在运行时从您的DI Container中替换。


1
2017-12-13 16:20



这意味着我们必须为我们的VM提供无参数构造函数。 - Pavel Voronin
是的,它只是为了能够在Xaml中呈现它们。使用常规构造函数用于VM,但使用空构造函数重载。请记住,因为在构建View时,您基本上是热交换VM - 在创建VM并将其传递到代码隐藏时,DI容器仍将使用较长的DI'd构造函数创建类。 - Patrick McCurley
如果你非常担心使用空构造函数滥用虚拟机的可能性 - 如果在构造时没有构造空构造函数,你总是会抛出异常,因此安全地限制以这种方式创建VM到Xaml布局引擎。 Windows.ApplicationModel.DesignMode.DesignModeEnabled或System.ComponentModel.DesignerProperties.GetIsInDesignMode将检查此项。 - Patrick McCurley
我更担心View将尝试应用绑定,这将导致读取需要注入依赖项的属性。我不记得在对象生命周期中第一次应用绑定的时间。我们还有复合VM和复合Vs. - Pavel Voronin
如果设置了设计模式,只需在这些特定属性中添加条件即可返回默认值。 - Patrick McCurley