【干货】个人工作文档节选:XAML MVVM 框架易用性细节优化Tips

1    易用性细节优化

1.1 代码片段

在ViewModel内,会有大量重复性的在Property set中激发 INotifyPropertyChanged.PropertyChanged 事件的代码。 这种属性用已有的代码片段已经很难高效的输入。使用合适的代码片段在VM设计时 不会因为过于机械的修改影响设计思路

1.1.1  Property Code Snippets

在项目模板中加入对应的code snippet

Sample:

键入 propvm [Tab]  [Tab]后 产生如下代码

     

复制代码
  
private int _PropertyName;
public int PropertyName
{
  get   {     return _PropertyName;   } set   {   _PropertyName=value;   RaisePropertyChanged(()=>PropertyName);   } }
复制代码

 

 

 

 

1.1.2  Command Code Snippets  

同样作为Command<Object> 的属性 也需要类似的code snippets

Sample:

键入 propcmd[Tab]  [Tab]后 产生如下代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private Command<Object> _CommandName=
    new     Command<Object> (
        p=>{},
        p=>true);
    
public Command< Object > CommandName
{
    get
    {  
        return _CommandName;  
    }  
    set  
    {  
        _CommandName =value;  
        RaisePropertyChanged(()=>CommandName);  
    }
    
}
    
  
          

 

1.2 设计时支持

作为MVVM的UI开发设计基础,一个生产力足够高的框架应当能够为设计时提供VM的结构成员和设计时数据支持。

 

1.2.1  步骤:在设计视图添加设计时VM.

假设我们有一个ViewModel 类型为  My.Project.TestViewModel

在设计器正确引入如下命名空间时

             

   
   

<UserControl
    xmlns:d=”http://schemas.microsoft.com/expression/blend/2008”
    xmlns:vm=”clr-namespace:My.Project”
    …>

   

   

</UserControl>

   

 

   
   

 

在设计器根节点加入

             

   
   

<d:FrameworkElement.DataContext>
        <vm:TestViewModel />

   

</d:FrameworkElement.DataContext>

   

 

   
   

 

这时设计器会为View指定一个TestViewModel的新实例,此时绑定会用这个新实例为模板进行设计时支持,比如所见即所得的绑定结果显示,以及模板设计支持。

对于早期版本的 VS,或者WPF/SL 以外不能支持 blend设计时命名空间的平台,d:DataContext 不被设计时支持, 这时候我们可能需要直接使用 <FrameworkElement.DataContext> 标记。这样做的代价可能是额外产生一个 ViewModel 对象引用。 如果我们能够控制好 ViewModel 默认构造函数中调用的资源,这样做问题并不大,不失为一种办法。

1.2.2  步骤:在VM添加设计时数据与逻辑

由于设计时设计器会创建一个VM实例来帮助设计,VM的设计需要注意以下几点

l  VM要具有默认构造函数,否则设计器无法将其实例化

l  VM中的逻辑要能够判断当前运行环境是否在设计时

n  使用大量珍贵资源的逻辑在设计时不允许运行,比如

u  Timer 逻辑

u  IO操作

 

应当在适当位置添加 “IsInDesignMode” 静态属性,建议在 ViewModelBase中添加。

    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
            static bool? _IsInDesignMode;
 
 
            /// <summary>
            /// <para>Gets if the code is running in design time. </para>
            /// <para>读取目前是否在设计时状态。</para>
            /// </summary>
            public static bool IsInDesignMode
            {
                get
                {
 
                    return (
                        _IsInDesignMode
                        ??
                        (
 
                            _IsInDesignMode =
#if SILVERLIGHT_5||WINDOWS_PHONE_8||WINDOWS_PHONE_7
                                DesignerProperties.IsInDesignTool
#elif NETFX_CORE
                                Windows.ApplicationModel.DesignMode.DesignModeEnabled
#else
                                (bool)System.ComponentModel.DependencyPropertyDescriptor
                                .FromProperty(
                                    DesignerProperties.IsInDesignModeProperty,
                         <br><br><br><br>           typeof(System.Windows.FrameworkElement))
                                .Metadata
                                .DefaultValue
#endif
                        ))
                        .Value;
                }
 
            }

 

      

 

在实现了这个属性之后 在具体Vm的构造函数或Onload事件中用户就可以添加伪数据,也可以避免不能再设计时调用的功能被调用

比如下面这段代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protected override async Task OnBindedViewLoad(MVVMSidekick.Views.IView view)
{
    await base.OnBindedViewLoad(view);
 
    if (IsInDesignMode)
    {
        HelloWorld = "Hello Mvvm world, Design mode sample";
    }
    else
    {
        if (Id == null)
        {
            Id = Guid.NewGuid().ToString();
        }
 
        GetValueContainer(x => x.CountDown).GetNullObservable()
            .Subscribe(
                _ =>
                {
                    HelloWorld = string.Format("Loading {0}", CountDown);
                }
            );
    }
 
}

 

 

 当然, MVVM-Sidekick 这些方面做的都很不错。

posted @   MSFT:waywa 韦恩卑鄙  阅读(1790)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示