WPF学习笔记04-MVVM和别的一些东西的补充

<0x00> 相对更正规的MVVM的写法

前一篇文章不是讲MVVM模型嘛,然后这几天看了看别人写的代码
确实有很多值得学习的地方

单独拆个BaseViewModel出来

之前讲到ViewModel要实现接口INotifyPropertyChanged来通知前端属性更改
基本上所有的VM都要用到的,所以最好就是有个BaseViewModel类,给所有的VM继承
具体代码如下

namespace WPFTest.VM
{
    public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        internal void NotifyPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

其实就是把那些代码单独拆出来了
然后所有的VM继承这个类就好了

之前也讲到RelayCommand类也是经常用到的工具类
所以一般这两个类的文件会放在同一个文件夹下

这里的命名空间也进行了规范(我这里为了简单就只写缩写了)
反正就是M/V/VM分三块地就行了
具体还是按着规范怎么舒服怎么来

另一种更舒适的方式添加DataContext

之前在前端引入VM的上下文是靠对应.cs文件里加this.DataContext=this;实现
现在有相对舒适的做法
首先要在.xamlxmlns中引入命名空间
然后加入具体控件的DataContext
具体要添加的代码如下

<Window ...
        xmlns:vm="clr-namespace:WPFTest.VM"
        ...>
    ...
    <Window.DataContext>
        <vm:ViewModel/>
    </Window.DataContext>
    ...
</Window>

这里的vm可以随便改的,ViewModel是具体的VM
这样写的话就尽可能避开对应的.cs,尽可能把前端实现交给.xaml

<0x01> 关于窗口透明化

之前是在Window标签里设置AllowTransparency=TrueBackground="Transparent"来实现
但这样实现的窗口性能会受很大影响(相关分析可以看大佬lindexi的博客)
简单来说就是这样写会相对频繁的申请内存,让CPU和内存的负荷加大
所以怎么办呢,我们也可以通过WindowChrome实现
更多的信息可以看大佬walterlv的博客
还有大佬丑萌气质狗的博客
我这里就接着我的代码改改了

具体修改的代码如下

<!--前一个是隐藏window默认控件的,后一个是仅允许最小化的意思-->
<!--具体也不清楚为啥,后一个必须是CanMinimize或NoResize才有透明-->
<Window ...
        WindowStyle="None"  
        ResizeMode="CanMinimize"
        ...>
    <!--修改WindowChrome-->
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1"/>
    </WindowChrome.WindowChrome>
    <!--别的代码-->
    <!--在Template里设置背景透明,一定别忘加ContentPresenter-->
    <Window.Template>
        <ControlTemplate TargetType="Window">
            <Border Background="Transparent">
                <Border CornerRadius="10"
                        Margin="10">
                    <Border.Background>
                        <LinearGradientBrush StartPoint="0,0"
                                             EndPoint="0,1">
                            <GradientStop Color="#392669"
                              Offset="0"/>
                            <GradientStop Color="#46204F"
                              Offset="1"/>
                        </LinearGradientBrush>
                    </Border.Background>
                    <Border.Effect>
                        <DropShadowEffect Color="Gray"
                              ShadowDepth="0"
                              BlurRadius="10"
                              Opacity=".5"
                              Direction="0"/>
                    </Border.Effect>
                    <ContentPresenter ClipToBounds="True"/>
                </Border>
            </Border>
        </ControlTemplate>
    </Window.Template>
    <!--别的控件-->
</Window>

还有我们原来负责最小化和关闭程序的两个按钮要加上WindowChrome.IsHitTestVisibleInChrome="True"
这个原理在丑萌气质狗的博客里有讲

(其实建议不搞异型窗口,容易出很多莫名其妙的问题)

<0x02> 一些常用的Nuget包

WPF的强大还体现在有很多Nuget
这些包大多是些UI组件,使WPF也可以方便的实现现代化的UI
我自己在研究的有ModernWPFFluentWPF
MordernWPF提供了些现代化的窗口和组件
FluentWPF实现了Fluent设计的UI,看着好看很多
这两个用得应该还算广吧(我在很多的WPF项目里看到有用的)
性能方面还没怎么试(没研究明白)

还有一个不是专门给WPF用的,而是方便MVVM设计的
CommunityToolkit.Mvvm,很好用的
平时我们写MVVM模式总是要像最上面一样写一个BaseViewModel还有一个RelayCommand
这些常用的基础类已经在这个包里写好了
尤其是这玩意8.0版本加入了源代码生成器的特性,现在写属性和前端通知就很方便
具体可以看B站up-十月的寒流的视频
(人家是真大佬,他的视频做的都很不错的)
(所以我的博客就摸了😋)

Licensed under CC BY-NC-SA 4.0