WPF仿网易云搭建笔记(2):组件化开发

文章目录

前言

这次我们来讲解一下WPF 的组件化开发流程,组件化开发是是可以极大降低我们页面开发难度,降低代码耦合的方法。这让我们可以将任意WPF界面进行拆解。因为我写过Vue,所以我会按照Vue的逻辑将WPF进行组件化开发。

专栏和Gitee仓库

WPF仿网易云 Gitee仓库
WPF仿网易云 CSDN博客专栏

依赖属性

WPF为了提高性能,限制了Binding的使用。需要将属性提前注册为依赖属性或者附加属性,才能解决使用Binding语法。原因是每个能binding的属性需要在内存中开辟存储空间。WPF默认不能Binding,需要主动声明才可以。

这个就是为什么Elelctron,Fullter等内存开销那么大,是因为他们的将可能没用的的内存空间也设置了。

博客园 痕迹g WPF依赖属性详解
B站 十月的寒流 WPF 中依赖属性及附加属性的概念及用法
B站 微软系列技术教程 WPF依赖属性详解

实战:缩小,全屏,关闭按钮

这里我讲解一下Window和UserControl两者的区别。Window就是整个窗口,UserControl就是控件。Window负责窗口的一些方法,比如拖拽,缩小放大。而我们是组件化开发,我们就需要将主窗口的this传给子组件

依赖属性操作封装

这里先去看我这个总结的博客。

WPF 用户控件依赖属性赋值

主窗口传递this本身给TitleView标题控件

因为我们是View和ViewModel开发,所有的View只有传递参数和暴露依赖属性的作用,实际的业务是ViewModel去做的。

所以我们传递的方向是
MainWindow MainWindowViewModel TitleView的MainWindow依赖属性 TitleViewModel的MainWindow

主要代码

MainWindow.xmal

xml 复制代码
<Window x:Class="BlankApp1.Views.MainWindow"
        ......>
    <!--需要主动设置名称,不然会Binding错误-->
    <Window.DataContext>
        <ViewModels:MainWindowViewModel x:Name="MainWindowViewModel" />
    </Window.DataContext>
    <DockPanel LastChildFill="True">
		<!--其它代码-->
        <Grid DockPanel.Dock="Top"
              MouseLeftButtonDown="Grid_MouseLeftButtonDown"
              Height="auto">
            <!--手动指定DataContext-->
            <Views:TitleView  MainWindow="{Binding MainWindow, ElementName=MainWindowViewModel}"  />
        </Grid>

    </DockPanel>
</Window>

MainWindow.cs

csharp 复制代码
    public partial class MainWindow : Window
    {

        public MainWindowViewModel ViewModel { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            //重定向ViewModel
            ViewModel = (MainWindowViewModel)DataContext;
            ViewModel.MainWindow = this;
        }
    }

依赖属性方法封装

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace BlankApp1.Utils
{
    public class MyWpfExtension<View> where View : class
    {
        
        
        /// <summary>
        /// 简化依赖注入代码
        /// </summary>
        /// <typeparam name="View"></typeparam>
        /// <typeparam name="Value"></typeparam>
        /// <param name="name"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public DependencyProperty DependencyPropertySet<Value>(string name, Action<View, Value> action)
        {
            var res = DependencyProperty.Register(name, typeof(Value), typeof(View), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                new PropertyChangedCallback((item, res) =>
                {
                    var model = item as View;
                    var value = (Value)res.NewValue;
                    if (model != null)
                    {
                        action(model, value);
                    }
                    else
                    {
                        throw new Exception("model value is null");
                    }
                })));
            return res;
        }

    }
}

TitleView.cs

csharp 复制代码
namespace BlankApp1.Views
{
    /// <summary>
    /// TitleView.xaml 的交互逻辑
    /// </summary>
    public partial class TitleView : UserControl
    {

        //这个只是为了代码提示,不涉及逻辑
        public MainWindow MainWindow { get; set; }

        //初始化依赖属性构造器
        public  static readonly MyWpfExtension<TitleView> MyWpfExtension = new MyWpfExtension<TitleView>();

        //这个是简化后的依赖属性
        public static readonly DependencyProperty MainWindowProperty = 
            MyWpfExtension.DependencyPropertySet<MainWindow>("MainWindow", (view, value) =>
        {
        	//通过依赖属性来获取MainWindow的对象
            view.TitileViewModel.MainWindow = value;
        });

        /// <summary>
        /// DataContext的数据
        /// </summary>
        public TitileViewModel TitileViewModel { get; set; }

        public TitleView()
        {
            InitializeComponent();
            //拿到DataContext数据重定向
            TitileViewModel = (TitileViewModel)DataContext;
        }
    }
}

TitleViewModel

csharp 复制代码
using BlankApp1.Models;
using BlankApp1.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace BlankApp1.ViewModels
{
    public partial class TitileViewModel:ObservableObject
    {

        public RelayCommand CloseWindow { get; set; }

        public RelayCommand MaxOrNormalWindow { get; set; }

        public RelayCommand MiniWindow { get; set; }

        public MainWindow MainWindow { get; set; }


        public TitileViewModel() {
			//.......其它代码
            CloseWindow = new RelayCommand(() => {
                MainWindow.Close();
                Debug.WriteLine("关闭窗口");
            });

            MaxOrNormalWindow = new RelayCommand(() => {
                if(MainWindow.WindowState == WindowState.Normal)
                {
                    MainWindow.WindowState = WindowState.Maximized;
                    MainWindow.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
					MainWindow.MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
                }
                else
                {
                    MainWindow.WindowState = WindowState.Normal;
                }
                Debug.WriteLine("最大化或正常窗口");
            });
            MiniWindow = new RelayCommand(() => {
                MainWindow.WindowState = WindowState.Minimized;
                Debug.WriteLine("缩小窗口");
            });
        }

    }
}

TitleViewModel

就是绑定按钮事件,我就不放了

详细代码看我的Gitee仓库地址

WPF仿网易云 Gitee仓库

实现效果

相关推荐
张哈大11 分钟前
【 java 虚拟机知识 第二篇 】
java·开发语言·jvm·笔记
Magnum Lehar1 小时前
wpf游戏引擎content/Asset.cs
游戏引擎·wpf
安审若无1 小时前
Hive的索引使用如何优化?
数据仓库·hive·hadoop
玻璃瓶和纸飞机2 小时前
Java常用类库大全(学习笔记)持续更新中
java·笔记·学习
Magnum Lehar2 小时前
wpf游戏引擎下的Geometry实现
java·游戏引擎·wpf
菜一头包2 小时前
QT5中的QGraphics图形视图框架学习笔记(Item、Scene和View)
笔记·qt·学习
Java Fans2 小时前
WPF调用Python心率监测脚本解决方案
开发语言·python·wpf
rufeike7 小时前
Redis学习笔记
redis·笔记·学习
晨曦backend10 小时前
Vim 替换命令完整学习笔记
笔记·学习·vim
蒙奇D索大11 小时前
【11408学习记录】[特殊字符] 速解命题核心!考研数学线性代数:4类行列式满分技巧(含秒杀公式)
笔记·学习·线性代数·考研·改行学it