没有。 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)
- 总是生成一些虚假的设计时数据