MVVM 是不是会停止 Visual Studio 设计器显示 xaml 的能力?

Posted

技术标签:

【中文标题】MVVM 是不是会停止 Visual Studio 设计器显示 xaml 的能力?【英文标题】:Does MVVM stop the ability for the Visual Studio Designer to show xaml?MVVM 是否会停止 Visual Studio 设计器显示 xaml 的能力? 【发布时间】:2017-09-24 05:17:29 【问题描述】:

我在我的程序中注意到,当我进行大量复杂绑定时,Visual Studio 无法正确显示 xaml。

MVVM 及其众多绑定是否会导致这种情况?在 Visual Studio 设计器中显示 xaml 以完全删除绑定是最安全的方法吗?

【问题讨论】:

XAML 设计器不能很好地使用 MVVM。但我不会因为头皮发痒就用电锯砍掉我的头。 这与MVVM无关,而是VS中的XAML设计器。 Visual Studio 中的 XAML 设计器和它产生的子进程完全是错误的,并且已经存在了大约 3 年。来自诸如 冻结 VS 之类的烦恼;属性编辑器不起作用。 改用 Expression Blend(如果可以的话)。我从来没有遇到过EB问题 停止使用拖放,只需键入 XAML。它的速度提高了 1000 倍,您可以得到更清晰、更清晰的标记,而且不会很糟糕。 @MickyD:Expression Blend 多年来不存在。现在有 Blend For Visual Studio。但是,Visual Studio 使用与 Blend 相同的 XAML 设计器。那你在说什么? @Liero 借口,借口。当你醒来并发现自己在矩阵中时,你会觉得“这只是文本,我什么都没看到,啊,我刚刚被章鱼机器人杀死了” 【参考方案1】:

没有。 MVVM 的核心原则之一是设计者支持。该原理在 Expression Blend 设计器(Resp Blend for Visual Studio)工具之后称为“可混合性”。请注意,Visual Studio 使用相同的设计器。

使用 MVVM,您可以通过数据绑定到设计时数据来获得更好的设计时支持。例如,在 DataGrid 或 ListBox 中,您可以在设计器中看到数据绑定时实际项目的外观。

破坏设计器与绑定的复杂性无关

您只需要遵循一些简单的原则并了解设计器中发生了什么。

首先,Visual Studio 设计器在设计器进程中创建 ViewModel 的实例。您需要小心,不要在视图模型中执行此类代码,这可能会破坏设计器。以下是一些示例:

不要这样做

    这会破坏设计器,因为不允许 Visual Studio 设计器进行 DB 调用。

    //ctor
    public MyViewModel()
    
        using(var db = new MyDbContext() ... //
    
    

    在构造函数中调用 DB 或 FileSystem 无论如何都是不好的做法

    这会破坏设计器,因为 VS Designer 无权访问您的配置

    //ctor
    public MyViewModel()
    
       string configValue = ConfigurationManager.AppSettings["SomeProperty"]
    
    

    如果你数据绑定到一个属性,getter 会被实际执行。此代码破坏了设计器,因为 App.Current 是 Visual Studio 设计器,而不是您的应用程序!小心点。

    public class MyViewModel
    
       public string SomeProperty
       
           get  return App.Current.MainWindow.SomeProperty; 
       
    
    

    这会在绑定到 CountOfItems 时引发 NullReferenceException,因为 VS Designer 没有调用 Load()

    public class MyViewModel
     
       private List<string> _items; 
    
       public void Load()
       
           _items = new List<string> "Item1", "Item2" 
       
    
    
       public int CountOfItems
       
           get  return _items.Count; 
       
    
    

良好做法

只要在需要的地方检查你是否处于设计模式:

//ctor
public MyViewModel

    bool IsDesignMode => DesignerProperties.GetIsInDesignMode(new DependecyObject());

    public MyViewModel()
    
       if (IsDesignMode)
       
          //this will be shown in the designer
          Items = new List<string> "Item1", "Item2" 
       
    

    //INotifyPropertyChanged details ommited due to simplification
    public List<string> Items get; private set;

    public void Load()
    
       //optionally you may check IsDesignMode 
       using (var db = new MyDbContext())
         
           this.Items = db.Items.Select(i => i.Name).ToList();
       
    

我创建了代码 sn-p,我在其中使用了这种模式:

d:DataContext="d:DesignInstance Type=local:MyViewModelDesignTime, IsDesignTimeCreatable=True"

我实际上并没有直接实例化 ViewModel,但我注入了 ViewModel 的 DesignTime 版本:

public class MyViewModel()

    protected MyViewModel()
    
        //both runtime and design time logic. 
        //you may use IsDesignMode check if needed
    

    public MyViewModel(ISomeExternalResource externalResource) : this();
    
        //this is executed only at run time
        _externalResource = externalResource;
        Items = externalResouce.GetAll();
    

    public List<string> Items get; protected set;


public class MyViewModelDesignTime : MyViewModel

    public MyViewModelDesignTime () : base()
     
        //this will be show in the designer
        Items = new List<string>  "Item1", "Item2" ;
    

如果您的设计器仍然中断并且您不知道原因,您可以将另一个 Visual Studio 实例附加到 xaml 设计器进程,它会很好地显示有问题的代码行。

最后但同样重要的是,您可以轻松关闭 ViewModel 的实例化。只需在 d:DataContext 中设置IsDesignTimeCreatable=false

回顾

    检查可以由 xaml 执行的视图模型的所有代码执行路径 设计流程 不要在这些执行路径中访问数据库、Web 服务或文件系统 不要访问静态资源,例如Application.Current,因为可能没有正确初始化 检查所有数据绑定属性的getter。他们可能会尝试返回设计者未初始化的内容。 对设计器和运行时执行路径使用分支(例如 if..else) 总是生成一些虚假的设计时数据

【讨论】:

"最后但同样重要的是,您可以轻松关闭 ViewModel 的实例化。只需在 d:DataContext 中设置 IsDesignTimeCreatable=false"。或者,在 XAML 设计器的工具栏上,选择禁用项目代码按钮 - 来源:docs.microsoft.com/en-us/visualstudio/designers/… @MotKohn:唯一的问题是当设计器失败时按钮通常不可见:) 如果您将Dispatcher 用于async 任务,请注意。除此之外,这是一个很棒的答案!干得好@Liero 非常感谢!我一直在处理这个问题一段时间,最后用谷歌找到了这个答案。【参考方案2】:

是的,如果您的绑定和 Viewmodel 很复杂,那么您的设计时间可能无法正常工作。但是,如果您想要设计时支持,则创建一个虚拟视图模型,您可以将其设置为设计时视图模型,它将仅在设计时使用虚拟视图模型。检查下面的代码。

d:DataContext="d:DesignInstance Type=yourviewmodetype, IsDesignTimeCreatable=True"

【讨论】:

以上是关于MVVM 是不是会停止 Visual Studio 设计器显示 xaml 的能力?的主要内容,如果未能解决你的问题,请参考以下文章

visual studio写完程序,编译以后,再改程序,编译器不编译改过后的程序

Visual Studio 2015 (C++):在第一次构建错误时停止编译(不是第一个项目)

如何在 Visual Studio 中为客户端 MVVM 语言获取 Razor 智能感知?

知道啥会导致 Visual Studio 2013 中的“vshost32.exe 已停止工作”吗?

Visual Studio 分析:从代码开始/停止

visual studio 是否可以远程监控局域网电脑