MVVM是否会阻止Visual Studio Designer显示xaml?

我在我的程序中注意到,当我有很多复杂的绑定时,visual studio没有正确显示xaml。

MVVM及其众多绑定会导致这种情况吗? 在visual studio designer中显示xaml以完全删除绑定是最安全的方法吗?

不是.MVVM核心原则之一是设计师支持。 在Expression Blend设计器(resp Blend for Visual Studio)工具之后,该原理称为“Blendability”。 请注意,Visual Studio使用相同的设计器。

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

打破设计师与绑定的复杂性无关

您只需遵循一些简单的原则,并了解设计师正在发生的事情。

首先,Visual Studio设计器在设计器进程中创建ViewModel的实例。 您需要小心,不要在viewmodel中执行这样的代码,这可能会破坏设计器。 这里有些例子:

不要这样做

  1. 这将破坏设计器,因为不允许Visual Studio Designer进行数据库调用。

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

    无论如何,在constuctor中调用DB或FileSystem是不好的做法

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

     //ctor public MyViewModel() { string configValue = ConfigurationManager.AppSettings["SomeProperty"] } 
  3. 如果你数据绑定到一个属性,那么getter就会被执行。 此代码打破了设计器,因为App.Current是Visual Studio Designer,而不是您的应用程序! 小心一点。

     public class MyViewModel { public string SomeProperty { get { return App.Current.MainWindow.SomeProperty; } } } 
  4. 绑定到CountOfItems时会导致NullReferenceException,因为VS Designer不会调用Load()

     public class MyViewModel { private List _items; public void Load() { _items = new List{ "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{ "Item1", "Item2" } } } //INotifyPropertyChanged details ommited due to simplification public List 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(); } } } 

我已经创建了代码片段,我使用这种模式:

 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 Items {get; protected set;} } public class MyViewModelDesignTime : MyViewModel { public MyViewModelDesignTime () : base() { //this will be show in the designer Items = new List { "Item1", "Item2" }; } } 

如果您的设计师无论如何都要破解而您不知道为什么,您可以将另一个visual studio实例附加到xaml设计器流程中,它将显示有问题的代码行。

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

概括

  1. 检查viewmodel的所有代码执行路径,这些路径可以由xaml设计器进程执行
  2. 不要在这些执行路径中访问数据库,Web服务或文件系统
  3. 不要访问静态资源,例如Application.Current,因为可能无法正确初始化
  4. 检查所有数据绑定属性的getter。 他们可能会返回一些未被设计师初始化的东西。
  5. 对设计器和运行时执行路径使用分支(例如if..else)
  6. 总是生成一些虚假的设计时数据

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

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