C# wpf 运行时替换方法实现mvvm自动触发刷新

文章目录

  • 前言
  • 一、如何实现?
    • 1、反射获取属性
    • 2、定义替换方法
    • 3、交换属性的setter方法
  • 二、完整代码
    • 1、接口
    • 2、项目
  • 三、使用示例
    • 1、倒计时
      • (1)、继承ViewModelBase
      • (2)、定义属性
      • (3)、属性赋值
      • (4)、窗口关联ViewModel
      • (5)、xaml绑定
  • 总结


前言

我们知道,使用wpf的绑定功能,代码触发界面改变时需要在属性的setter触发PropertyChanged事件,以达到界面刷新的效果。上一章我们简化了触发流程,但是依然需要在每个属性的setter中调用方法。本章将再进一步简化,实现setter不需要调方法就可以自动触发界面刷新


一、如何实现?

1、反射获取属性

通过反射获取类的所有公有属性

var propertyInfos = type.GetProperties(bindingAttr: BindingFlags.Instance | BindingFlags.Public);

2、定义替换方法

定义的用于替换属性setter的方法,确保参数类型兼容。设置NoInlining确保不会被内联优化失去函数地址。再方法中触发RaisePropertyChangedEvent。

 [MethodImpl(MethodImplOptions.NoInlining)] void Setter0_obj(object value) { //此时Setter0_obj已经被替换成了属性的setter,调用会进入属性的setter中。Setter0_obj(value);RaisePropertyChangedEvent(_propertyInfos![0].Name); }

3、交换属性的setter方法

将定义的替换方法与属性的setter交换。MethodHooker.SwapMethod可以去搜索C#运行时替换函数的方法,本章的只是去掉了unsafe的实现。

var oldSetter = propertyInfos[i].GetSetMethod();
if (oldSetter != null && oldSetter.IsPublic)
//定义了set且set为公有时才交换。
{MethodInfo newSetter= type.BaseType.GetMethod("Setter0_obj", BindingFlags.Instance | BindingFlags.NonPublic)!;MethodHooker.SwapMethod(oldSetter, newSetter);
}

二、完整代码

1、接口

/// <summary>
/// ViewModelBase,继承此类可以简化属性的定义,不需要手动触发RaisePropertyChangedEvent。
/// 用法:继承此类,属性为公有,set为公有且非内联,设置属性就会自动触发mvvm的binding。
/// 实验性质,其他.net版本无效,在.net6.0是稳定的,。x64、x86,debug和release都可以使用。release需要给set设置[MethodImpl(MethodImplOptions.NoInlining)],否则无法实现函数交换。
/// 目前支持64个属性,单个属性(struct)最大128字节,需要更多可以自行调用GenSetters生成代码。
/// </summary>
public abstract class ViewModelBase : INotifyPropertyChanged
{public event PropertyChangedEventHandler PropertyChanged;public ViewModelBase();//依然提供此方法用于手动触发protected void RaisePropertyChangedEvent([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "");
}

2、项目

vs2022 .net 6.0项目。
https://download.csdn.net/download/u013113678/89241921
注:目前版本只能在.net6.0中正常使用,x64、x86、debug、release都没问题。其他.net版本大概率无效果或者异常。属于实验性质,请根据需要下载。


三、使用示例

1、倒计时

(1)、继承ViewModelBase

public class TimeTick : ViewModelBase

(2)、定义属性

set为公有,以及[MethodImpl(MethodImplOptions.NoInlining)]避免内联。支持非缺省set方法体,即可以在set中加入一些逻辑。

public class TimeTick : ViewModelBase
{public double Seconds { get; [MethodImpl(MethodImplOptions.NoInlining)] set; }=60;
}

(3)、属性赋值

public TimeTick()
{var time = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(1000) };time.Tick += (s, e) =>Seconds--;     time.Start();
}

(4)、窗口关联ViewModel

public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();DataContext = new TimeTick();}
}

(5)、xaml绑定

 <TextBlock Text="{Binding Seconds}" />

效果预览
在这里插入图片描述


总结

以上就是今天讲述的内容,替换函数原理很简单,但是具体实现还是比较麻烦的,尤其是需要适配不同的.net版本,本文目前只支持.net6.0。还有就是函数的参数,引用和值类型的区分,以及值类型的传值兼容,这些都是通过多次尝试才找个合理的方式。通过本文简化的ViewModelBase使用变的非常方便了,除了需要给set添加非内联属性,其他已经和普通属性没有区别。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【目标检测】DEtection TRansformer (DETR)

一、前言 论文&#xff1a; End-to-End Object Detection with Transformers 作者&#xff1a; Facebook AI 代码&#xff1a; DEtection TRansformer (DETR) 特点&#xff1a; 无proposal&#xff08;R-CNN系列&#xff09;、无anchor&#xff08;YOLO系列&#xff09;、无NM…

pycharm配置wsl开发环境(conda)

背景 在研究qanything项目的过程中&#xff0c;为了进行二次开发&#xff0c;需要在本地搭建开发环境。然后根据文档说明发现该项目并不能直接运行在windows开发环境&#xff0c;但可以运行在wsl环境中。于是我需要先创建wsl环境并配置pycharm。 wsl环境创建 WSL是“Windows Su…

EasyExcel 处理 Excel

序言 本文介绍在日常的开发中&#xff0c;如何使用 EasyExcel 高效处理 Excel。 一、EasyExcel 是什么 EasyExcel 是阿里巴巴开源的一个 Java Excel 操作类库&#xff0c;它基于 Apache POI 封装了简单易用的 API&#xff0c;使得我们能够方便地读取、写入 Excel 文件。Easy…

【讲解下如何解决一些常见的 Composer 错误】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【二等奖水平论文】2024五一数学建模C题22页保奖论文+22页matlab和13页python完整建模代码、可视图表+分解结果等(后续会更新)

一定要点击文末的卡片&#xff0c;那是资料获取的入口&#xff01; 【高质量精品】2024五一数学建模C题成品论文22页matlab和13页python完整建模代码、可视图表分解结果等「首先来看看目前已有的资料&#xff0c;还会不断更新哦~一次购买&#xff0c;后续不会再被收费哦&#…

DRF解析器源码分析

DRF解析器源码分析 1 解析器 解析请求者发来的数据&#xff08;JSON&#xff09; 使用 request.data 获取请求体中的数据。 这个 reqeust.data 的数据怎么来的呢&#xff1f;其实在drf内部是由解析器&#xff0c;根据请求者传入的数据格式 请求头来进行处理。 drf默认的解…

电路笔记 : 电容电阻大小表示(103、104、151、2R5、R15的含义)

电容电阻大小表示 电阻 数字索位标称法 数字索位标称法就是在电阻体上用三位数字来标明其阻值。它的第一位和第二位为有效数字&#xff0c;第三位表示在有效数字后面所加“0”的个数.这一位不会出现字母。如果阻值是小数.则用“R”表示“小数点”.并占用一位有效数字&#xf…

eaapp怎么改地区?eaapp账号区域更改的简单操作教程分享

eaapp怎么改地区&#xff1f;eaapp账号区域更改的简单操作教程分享 EA App是由Electronic Arts艺电公司开发的官方游戏平台&#xff0c;为玩家提供了一个集中管理和探索EA游戏世界的平台。该平台提供了丰富的游戏库&#xff0c;包括热门游戏如《FIFA》和《Apex Legends》等。…

C语言——小知识和小细节17

一、未能给指针成功赋值 #include <stdio.h> #include <stdlib.h> #include <string.h>void GetMemory(char* p) {p (char*)malloc(20 * sizeof(char)); }void Test() {char* str NULL;GetMemory(str);strcpy(str, "Hello World!");printf(&quo…

Java网址url工具类

功能描述 无需引入三方依赖文本匹配网址&#xff08;支持多个&#xff09;网址解析&#xff08;包括协议、主机、路径、参数等&#xff09; package com.qiangesoft.image.utils;import org.springframework.util.Assert; import org.springframework.util.CollectionUtils;i…

Flutter笔记:Widgets Easier组件库(5)使用加减器

Flutter笔记 Widgets Easier组件库&#xff08;5&#xff09;&#xff1a;使用加减器 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress…

IO端子介绍及GPIO number计算

IO端子介绍 &#xff08;引脚&#xff0c;针脚&#xff09; 嵌入式系统的主芯片&#xff0c;有的IO资源少&#xff0c;有的IO资源多。 少的是这样的封装&#xff0c;IO管脚都在四周&#xff1b; 多的是这样的封装&#xff0c;IO 的PAD都在下面&#xff1a; MCU或MPU&#xff0c…

VS(Visual Studio)中查找项目里的中文字符

目录 正则表达式查找中文字符 正则表达式查找中文字符 在Visual Studio (VS) 中查找所有的中文字符&#xff0c;你可以使用其强大的查找和替换功能。不过&#xff0c;由于中文字符的范围非常广泛&#xff08;包括简体中文、繁体中文、日本汉字、韩国汉字等&#xff09;&#xf…

[1671]jsp教材管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 教材管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

springcloud自定义全局异常

自行创建一个实体类 /*** 全局异常处理类**/ ControllerAdvice public class GlobalExceptionHandler {ExceptionHandler(Exception.class) ResponseBody public Result error(Exception e){e.printStackTrace(); return Result.fail();}/*** 自定义异常处理方法* param e * re…

亚马逊云科技AWS将推出数据工程师全新认证(有资料)

AWS认证体系最近更新&#xff0c;在原有12张的基础上&#xff0c;将在2023年11月27日添加第13张&#xff0c;数据工程师助理级认证(Data Engineer Associate)&#xff0c;并且在2024/1/12前半价(省75刀&#xff1d;544人民币。 原有的数据分析专家级认证(Data Analytics Specia…

【论文阅读笔记】TS2Vec: Towards Universal Representation of Time Series

【论文阅读笔记】TS2Vec: Towards Universal Representation of Time Series 摘要 这段文字介绍了一个名为TS2Vec的通用框架&#xff0c;用于学习时间序列数据的表示&#xff0c;可以在任意语义层次上进行。与现有方法不同&#xff0c;TS2Vec通过对增强的上下文视图进行层次化…

Redis 实战1

SDS Redis 只会使用 C 字符串作为字面量&#xff0c; 在大多数情况下&#xff0c; Redis 使用 SDS &#xff08;Simple Dynamic String&#xff0c;简单动态字符串&#xff09;作为字符串表示。 比起 C 字符串&#xff0c; SDS 具有以下优点&#xff1a; 常数复杂度获取字符串…

每日一题(力扣213):打家劫舍2--dp+分治

与打家劫舍1不同的是它最后一个和第一个会相邻&#xff0c;事实上&#xff0c;从结果思考&#xff0c;最后只会有三种&#xff1a;1 第一家不被抢 最后一家被抢 2 第一家被抢 最后一家不被抢 3 第一和最后一家都不被抢 。那么&#xff0c;根据打家劫舍1中的算法 我们能算出在i…

Vmware虚拟机瘦身及Samba服务不可用问题解决

虚拟机磁盘空间膨胀是一个令人头疼的问题&#xff0c;特别是对许多搞开发的小伙伴。无论是做后台服务、嵌入式还是Android开发&#xff0c;都面临着这个难题。首先&#xff0c;操作系统本身就已占用不少空间&#xff0c;更新安装包&#xff0c;再下载一些开源软件&#xff0c;剩…