MVVM 是否会停止 Visual Studio 设计器显示 xaml 的能力? [英] Does MVVM stop the ability for the Visual Studio Designer to show xaml?

查看:15
本文介绍了MVVM 是否会停止 Visual Studio 设计器显示 xaml 的能力?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've noticed in my programs when I have alot of complicated bindings going on then visual studio does not show the xaml properly.

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

Does MVVM and its numerous bindings cause this? Is the safest way to show xaml in the visual studio designer to remove bindings completely?

推荐答案

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

No. One of the MVVM core principles is designer support. The principle is called "Blendability" after the Expression Blend designer (resp Blend for Visual Studio) tool. Note, that Visual Studio uses the same designer.

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

With MVVM you can achieve much better design time support by databinding to design time data. For example, you in DataGrid or ListBox you can see in the designer how the actual items looks like when databound.

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

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

You just need to follow few simple principles and understand what's going on in the designer.

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

First of all, Visual Studio designer creates instance of the ViewModel in the designer process. You need to be careful, that you don't execute such code in the viewmodel, that could break the designer. Here are some examples:

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

  1. This will break the designer, because Visual Studio Designer is not allowed to do DB calls.

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

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

calling DB, or FileSystem in constuctor is bad practice anyway

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

this breaks the designer, because VS Designer does not have access to your configuration

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

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

  • if you databind to a property, the getter is acually executed. This code breaks the designer, because App.Current is the Visual Studio Designer, not your app! Be carefull about it.

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

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

  • This will cause NullReferenceException when binding to CountOfItems, because VS Designer doesn't call Load()

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

  • 良好做法

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

    Good practices

    Just check if you are in the design mode wherever needed:

    //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();
           }
        }
    }
    

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

    I've created code snippet, where I use this pattern:

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

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

    I don't actually instantiace the ViewModel directly, but I inject DesignTime version of the viewmodel:

    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 设计器流程中,它会很好地显示有问题的代码行.

    If your designer breaks anyway and you don't know why, you can attach another instance of visual studio to the xaml designer process and it will nicelly show the problematic line of code.

    最后但并非最不重要的一点是,您可以轻松关闭实例化 ViewModel.只需在 d:DataContext

    Last, but not least, you can easily turn off instanciating the ViewModels. Just set IsDesignTimeCreatable=false in d:DataContext

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

    这篇关于MVVM 是否会停止 Visual Studio 设计器显示 xaml 的能力?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆