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

文章目录

  • 前言
  • 专栏和Gitee仓库
  • 依赖属性
  • 实战:缩小,全屏,关闭按钮
    • 依赖属性操作封装
    • 主窗口传递this本身给TitleView标题控件
    • 主要代码
      • MainWindow.xmal
      • MainWindow.cs
      • 依赖属性方法封装
      • TitleView.cs
      • TitleViewModel
      • TitleViewModel
      • 实现效果

前言

这次我们来讲解一下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


<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

    public partial class MainWindow : Window
    {

        public MainWindowViewModel ViewModel { get; set; }

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

依赖属性方法封装

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


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

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仓库

实现效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/235529.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JavaWeb学习专栏 | CSS篇】css简单介绍 css常用选择器集锦

个人主页&#xff1a;[兜里有颗棉花糖(https://xiaofeizhu.blog.csdn.net/) 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【JavaWeb学习专栏】【Java系列】 希望本文内容可以帮助到大家&#xff0c;一起加油吧&#xff01;…

安全访问服务边缘(SASE):解决第三方风险的全方位解决方案

随着数字化时代的到来&#xff0c;企业和组织对于网络安全的需求越来越迫切。传统的安全解决方案已经无法满足复杂多变的网络环境&#xff0c;因此新兴的安全访问服务边缘&#xff08;SASE&#xff09;应运而生。本文将介绍SASE的概念和工作原理&#xff0c;并重点阐述它作为第…

第二百回 如何获取App自身的信息

文章目录 1. 概念介绍2. 使用方法2.1 ClipOval2.2 ClipRRect 3. 示例代码 我们在上一章回中介绍了AspectRatio Widget相关的内容&#xff0c;本章回中将介绍剪裁类组件(Clip).闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里说的剪裁类组件主要是指对…

Koa2从零搭建restful API

Koa2从零搭建restful API: 创建项目文件夹并进入 mkdir koa-projectcd koa-project 初始化项目 npm init 安装 Koa npm install koa koa-router --save 编写示例代码&#xff0c;在 app.js 文件中编写以下代码&#xff1a; // koa项目的入口文件 const Koa require("koa…

018 OpenCV 人脸检测

目录 一、环境 二、分类器原理 2.1、概述 2.2、工作原理 三、人脸检测代码 一、环境 本文使用环境为&#xff1a; Windows10Python 3.9.17opencv-python 4.8.0.74 二、分类器原理 CascadeClassifier是OpenCV&#xff08;开源计算机视觉库&#xff09;中的一个强大的类…

想进阶JAVA高级程序员吗?多线程必学

❤️作者主页&#xff1a;小虚竹 ❤️作者简介&#xff1a;大家好,我是小虚竹。2022年度博客之星评选TOP 10&#x1f3c6;&#xff0c;Java领域优质创作者&#x1f3c6;&#xff0c;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;掘金年度人气作…

Truffle的基础语法与js测试语法

truffle编译 truffle compiletruffle部署 truffle migratetruffle测试 使用test文件夹下的所有文件测试 truffle test使用单个文件 测试 truffle test 文件所在位置assert断言 assert.equal 是一种常见的断言函数&#xff0c;用于测试两个值是否相等。它接受两个参数&…

代码随想录算法训练营第四十六天 _ 动态规划_背包问题总结。

学习目标&#xff1a; 动态规划五部曲&#xff1a; ① 确定dp[i]的含义 ② 求递推公式 ③ dp数组如何初始化 ④ 确定遍历顺序 ⑤ 打印递归数组 ---- 调试 引用自代码随想录&#xff01; 本文大多数内容引用自代码随想录 60天训练营打卡计划&#xff01; 学习内容&#xff1a; …

银行插件导致的Outlook客户端无法连接服务器问题

问题现象 最近遇到好些同事出现outlook客户端无法连接服务器的情况&#xff0c;具体现象就是右下角一直显示【正在尝试连接…】或者【需要密码】&#xff0c;点击【需要密码】按钮&#xff0c;输密码的弹窗是一个完全空白的页面。 此时打开word&#xff0c;右上角那里去登录o…

Postman获取token

问题描述 登录接口中带有token参数&#xff0c;其他接口需要带上token才能正确访问&#xff0c;利用接口查询用户信息时手动在headers中更新token信息并不方便。 解决方案 在登录接口中设置一个名为“token”的环境变量&#xff0c;value为登录接口跑通之后responseBody中返回…

科技提升安全,基于YOLOv4开发构建商超扶梯场景下行人安全行为姿态检测识别系统

在商超等人流量较为密集的场景下经常会报道出现一些行人在扶梯上摔倒、受伤等问题&#xff0c;随着AI技术的快速发展与不断普及&#xff0c;越来越多的商超、地铁等场景开始加装专用的安全检测预警系统&#xff0c;核心工作原理即使AI模型与摄像头图像视频流的实时计算&#xf…

⭐Unity 搭建UDP客户端(01) 配合网络调试助手测试

1.接收来自服务器的消息 using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using UnityEngine;public class UDPManager:MonoBehaviour {public string recvStr; //服务器返回值public string UDPClientAddRess "192.168.2.39&q…

【算法系列篇】递归、搜索和回溯(二)

文章目录 前言1. 两两交换链表中的节点1.1 题目要求1.2 做题思路1.3 代码实现 2. Pow(X,N)2.1 题目要求2.2 做题思路2.3 代码实现 3. 计算布尔二叉树的值3.1 题目要求3.2 做题思路3.3 代码实现 4. 求根节点到叶结点数字之和4.1 题目要求4.2 做题思路4.3 代码实现 前言 前面为大…

Uniapp - 环境搭建 vscode开发

uni-app 基础 创建 uni-app 项目方式 uni-app 支持两种方式创建项目&#xff1a; 通过 HBuilderX 创建&#xff08;需安装 HBuilderX 编辑器&#xff09; 通过命令行创建&#xff08;需安装 NodeJS 环境&#xff09; HBuilderX 创建 uni-app 项目 创建步骤 1.下载安装 H…

Demystifying DeFi MEV Activities in Flashbots Bundle

目录 笔记后续的研究方向摘要引言贡献 Demystifying DeFi MEV Activities in Flashbots Bundle CCS 2023 笔记 本文介绍了对 Flashbots 捆绑包中的去中心化金融 &#xff08;DeFi&#xff09; 矿工可提取价值 &#xff08;MEV&#xff09; 活动的研究。作者开发了ActLifter&am…

SiC SBD/超结MOS在工业电源上的应用-REASUNOS瑞森半导体

一、前言 工业电源是指用于工业及相关领域中的电子设备与设施的电源系统&#xff0c;其重要性体现在为各类工业设备提供稳定的电力保障&#xff0c;维护设备正常运行&#xff0c;故需具有稳定可靠、高效节能、安全耐用等特点。 常见的工业电源类型包括&#xff1a;交流电源、…

优优聚:美团外卖,领跑外卖市场,打造全新就餐体验

随着互联网的快速发展&#xff0c;外卖行业逐渐崛起&#xff0c;成为了人们日常生活中不可或缺的一部分。作为中国最大的外卖平台之一&#xff0c;美团外卖凭借其卓越的服务和不断创新的精神&#xff0c;成为了市场的领导者。本文将详细分析美团外卖的发展现状以及其未来的发展…

使用cmake构建的工程的编译方法

1、克隆项目工程 2、进入到工程目录 3、执行 mkdir build && cd build 4、执行 cmake .. 5、执行 make 执行以上步骤即可完成对cmake编写的工程进行编译 &#xff0c;后面只需执行你的编译结果即可 $ git clone 你想要克隆的代码路径 $ cd 代码文件夹 $ mkdir bu…

年入百万的知识付费网站如何搭建:如何以低成本实现高转化?

我有才知识付费平台 一、引言 随着知识经济的崛起&#xff0c;越来越多的知识提供者希望搭建自己的知识付费平台。然而&#xff0c;对于新手来说&#xff0c;如何以低成本、高效率地实现这一目标&#xff0c;同时满足自身需求并提高客户转化率&#xff0c;是一大挑战。本文将…

服务器GPU占用,kill -9 PID 用不了,解决办法

PID&#xff08;progress ID 进程ID&#xff09; 上图为占用情况&#xff0c;使用下面的指令都不管用 kill -9 PID kill -15 PID # 加入sudo 还是不行 # 等等网上的 chatgpt 提供的其他办法&#xff0c;一圈试了下来还是不管用最后解决办法 首先用下面的指令查看进程的树结构…