繁体   English   中英

MVVM是否会停止Visual Studio Designer显示xaml的功能?

[英]Does MVVM stop the ability for the Visual Studio Designer to show xaml?

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

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

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

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

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

您只需要遵循一些简单的原理,并了解设计器中发生的事情。

首先,Visual Studio设计器在设计器过程中创建ViewModel的实例。 您需要注意,不要在视图模型中执行此类代码,否则可能会破坏设计器。 这里有些例子:

不要这样

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

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

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

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

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

     public class MyViewModel { public string SomeProperty { get { return App.Current.MainWindow.SomeProperty; } } } 
  4. 绑定到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();
       }
    }
}

我创建了代码片段,在其中使用了以下模式:

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

我实际上并没有直接实例化ViewModel,但是我注入了ViewTime的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设计器过程中,它将很好地显示有问题的代码行。

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

概括

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

是的,如果您的绑定和Viewmodel很复杂,则有可能您的设计时间可能无法使用。 但是,如果需要设计时间支持,则可以创建一个虚拟视图模型,然后将其设置为设计时视图模型,该模型将仅在设计时使用虚拟视图模型。 检查以下代码。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM