wpf 基于Behavior库 的行为模块

Microsoft.Xaml.Behaviors 是一个用于WPF(Windows Presentation Foundation)的行为库,它的主要作用是允许开发者在不修改控件源代码的情况下,为控件添加自定义的行为和交互逻辑。行为库的核心思想是通过定义可重用的行为组件,将交互逻辑与UI控件解耦,从而提高代码的可维护性和可复用性。


1. 增强控件功能

  • 无需修改控件源码:在WPF中,控件的功能通常是固定的,但如果需要扩展控件的功能(例如为按钮添加双击事件、为文本框添加自动完成功能等),可以通过行为库来实现,而无需修改控件的源代码。
  • 动态添加行为:行为可以动态地附加到控件上,并在运行时生效,非常适合需要灵活交互的场景。

2. 将交互逻辑与UI解耦

  • 行为与UI分离:行为库使得交互逻辑与UI控件分离,开发者可以在不侵入控件代码的情况下,为控件添加自定义逻辑。
  • 行为复用:一旦定义了一个行为,它可以被多次复用到不同的控件上,减少了重复代码的编写。

3. 简化复杂的交互逻辑

  • 复杂交互的封装:某些复杂的交互逻辑(例如拖放操作、窗口关闭时的特殊处理、动画触发等)可以通过行为库封装为一个独立的行为,而不是直接写入控件的事件处理程序中。
  • 避免事件处理代码膨胀:使用行为库可以将事件处理逻辑集中管理,避免在代码背后堆积大量的事件处理代码。

4. 支持MVVM模式

  • MVVM的桥梁:在MVVM模式中,Behavior 可以作为视图(View)和视图模型(ViewModel)之间的桥梁。行为可以直接绑定到ViewModel中的命令(ICommand),从而将用户的交互操作(例如按钮点击、窗口关闭等)映射到ViewModel中的业务逻辑。
  • 减少代码背后的复杂性:在MVVM中,行为可以代替代码背后的逻辑(例如事件处理程序),使得代码更加清晰和简洁。

5. 灵活性和可扩展性

  • 自定义行为:开发者可以根据需求创建自定义的行为类,继承自 Behavior<T>(其中 T 是目标控件的类型,例如 ButtonTextBoxWindow 等)。
  • 内置行为Microsoft.Xaml.Behaviors 库还包含一些预定义的行为,例如 EventTriggerInvokeCommandAction 等,可以直接使用。

6. 与XAML无缝集成

  • 在XAML中使用行为:行为库可以与XAML无缝集成,开发者可以直接在XAML中为控件附加行为,而不需要编写C#代码。
    <Button><i:Interaction.Behaviors><behaviors:MyCustomBehavior /></i:Interaction.Behaviors>
    </Button>
    
  • 绑定支持:行为可以绑定到ViewModel中的命令或属性,使得行为逻辑可以动态变化。

示例:使用行为库的场景

  1. 拖放操作:为控件添加拖放行为。
  2. 窗口关闭时的特殊处理:如您提供的代码示例,当窗口关闭时,可以执行自定义命令(例如隐藏窗口而不是关闭它)。
  3. 按钮双击事件:为按钮添加双击行为,而不需要修改按钮的默认行为。
  4. 动画触发:当某个事件发生时(例如鼠标悬停),触发控件的动画。
  5. 自动完成:为文本框添加自动完成行为。

窗口关闭时的特殊处理

附加属性快捷键 : propdp

public static readonly DependencyProperty ClosingActionProperty =DependencyProperty.Register("ClosingAction",          // 属性名称typeof(ICommand),         // 属性类型typeof(HideViewBehavior), // 属性的宿主类 这里指定依赖属性的宿主类是 HideViewBehavior,表示这个依赖属性是属于 HideViewBehavior 类的。new PropertyMetadata(null) // 属性元数据 默认值为null);
using CommunityToolkit.Mvvm.Input;
using Microsoft.Xaml.Behaviors;
using System.Windows;
using System.Windows.Input;namespace BehaviorsModule
{public class HideViewBehavior : Behavior<Window>{public ICommand ClosingAction{get { return (ICommand)GetValue(ClosingActionProperty); }set { SetValue(ClosingActionProperty, value); }}public static readonly DependencyProperty ClosingActionProperty =DependencyProperty.Register("ClosingAction", typeof(ICommand), typeof(HideViewBehavior), new PropertyMetadata(null));protected override void OnAttached(){base.OnAttached();AssociatedObject.Closing += AssociatedObject_Closing;}private void AssociatedObject_Closing(object? sender, System.ComponentModel.CancelEventArgs e){e.Cancel = true;if (ClosingAction != null){ClosingAction.Execute(new object());}}}
}

给控件添加拖放操作

using Microsoft.Xaml.Behaviors;
using System.Windows;
using System.Windows.Input;namespace BehaviorsModule
{public class MoveViewBehavior: Behavior<Window>{protected override void OnAttached(){base.OnAttached();AssociatedObject.PreviewMouseDown += AssociatedObject_PreviewMouseDown;AssociatedObject.PreviewMouseMove += AssociatedObject_PreviewMouseMove;AssociatedObject.PreviewMouseLeftButtonUp += AssociatedObject_PreviewMouseLeftButtonUp;}private void AssociatedObject_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e){if (_isDragMoved){_isDragMoved = false;e.Handled = true;}}private void AssociatedObject_PreviewMouseMove(object sender, MouseEventArgs e){if (Mouse.LeftButton == MouseButtonState.Pressed && _pressedPosition != e.GetPosition(AssociatedObject)){_isDragMoved = true;AssociatedObject.DragMove();}}Point _pressedPosition;bool _isDragMoved = false;private void AssociatedObject_PreviewMouseDown(object sender, MouseButtonEventArgs e){_pressedPosition = e.GetPosition(AssociatedObject);}}
}

初始化窗体位置

    public class InitViewPostionBehavior : Behavior<Window>{public double xp{get { return (double)GetValue(xpProperty);}set { SetValue(xpProperty, value); }}// Using a DependencyProperty as the backing store for xp.  This enables animation, styling, binding, etc...public static readonly DependencyProperty xpProperty =DependencyProperty.Register("xp", typeof(double), typeof(InitViewPostionBehavior), new PropertyMetadata(0.0));public double yp{get { return (double)GetValue(ypProperty); }set { SetValue(ypProperty, value); }}// Using a DependencyProperty as the backing store for yp.  This enables animation, styling, binding, etc...public static readonly DependencyProperty ypProperty =DependencyProperty.Register("yp", typeof(double), typeof(InitViewPostionBehavior), new PropertyMetadata(0.0));private void InitializeFormPosition(){var workingArea = SystemParameters.WorkArea;double screenWidth = workingArea.Width;double screenHeight = workingArea.Height;double x = screenWidth / xp;double y = screenHeight / yp;AssociatedObject.Left = x;AssociatedObject.Top = y;}protected override void OnAttached(){base.OnAttached();InitializeFormPosition();}}

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

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

相关文章

overscroll-behavior-解决H5在ios上过度滚动的默认行为

1. 问题 开发H5的过程中&#xff0c;经常会有android和ios两边系统需要兼容的情况。在ios上一直有个问题是当H5内容触及到页面顶部或底部时&#xff0c;还是可以被人为的往下或往下拉动界面。当然可能有的情况是比较适用的&#xff0c;比如你往下拉动&#xff0c;然后在导航栏…

复杂对象的创建与组装 - 建造者模式(Builder Pattern)

建造者模式&#xff08;Builder Pattern&#xff09; 建造者模式&#xff08;Builder Pattern&#xff09;建造者模式&#xff08;Builder Pattern&#xff09;概述建造者模式结构图代码 talk is cheap&#xff0c; show you my code总结 建造者模式&#xff08;Builder Patter…

Linux-mac地址

mac地址 由6位16进制数组成。最高字节的最低位&#xff0c;0表示单播地址&#xff0c;1表示多播地址。最高字节的第二位&#xff0c;0表示全局地址&#xff0c;1表示本地地址。 单播地址&#xff1a;单播MAC地址用于一对一的通信模式&#xff0c;即从单一的源端发送到单一的目…

SAP学习笔记 - 豆知识14 - Msg 番号 M7562 - 取引Type WL 对应的番号範囲中不存在2025年度 OMBT

这种类似的以前也写过&#xff0c;原因就是自动採番的番号没弄。 比如跨年了&#xff0c;那该新年度的番号范围没弄啊&#xff0c;就会出这种错误。 把番号范围给加一下就可以了。 1&#xff0c;现象 比如点 VL02N 出荷传票变更 画面&#xff0c;点 出库确认 就会出如下错误…

一文理清JS中获取盒子宽高各方法的差异

前言 这段时间在研究一个反爬产品&#xff0c;环境检测用到了很多个盒子宽高取值方法&#xff0c;如window.outerWidth、window.screen.availWidth&#xff0c;各个方法取值结果不大相同&#xff0c;在此记录下遇到的方法。 各宽方法区别 这里就讲解下各宽度方法的区别&…

sqoop将MySQL数据导入hive

使用脚本加载数据 MySQL有一张表 hive创建一张相同的表 编写脚本同步数据 [rootmaster sqoop]# vim stu.sh#!/bin/bash SQOOP/usr/local/soft/sqoop-1.4.6/bin/sqoop $SQOOP import --connect jdbc:mysql://192.168.67.100:3306/sqoop \--username root \--password 123456 \-…

Docker Compose编排

什么是 Docker Compose? Docker Compose 是 Docker 官方推出的开源项目&#xff0c;用于快速编排和管理多个 Docker 容器的应用程序。它允许用户通过一个 YAML 格式的配置文件 docker-compose.yml 来定义和运行多个相关联的应用容器&#xff0c;从而实现对容器的统一管理和编…

[羊城杯 2024]hiden

一顿解压之后发现有两个文件&#xff1a; 尝试了Rot47解密&#xff0c;得到一个看起来挺像一回事的解码结果&#xff1a; 再将得到的解码结果试试Rot13解密&#xff0c;成功得到正确的解码结果&#xff1a; import wave with open(flag.txt, rb) as f:txt_data f.read()file_l…

LeetCode - 初级算法 数组(只出现一次的数字)

只出现一次的数字 这篇文章讨论如何找到一个数组中只出现一次的数字,确保算法的时间复杂度为线性,且只使用常量额外空间。 免责声明:本文来源于个人知识与公开资料,仅用于学术交流。 描述 给定一个非空整数数组 nums,除了某个元素只出现一次以外,其余每个元素均出现两…

【谷歌开发者月刊】十二月精彩资讯回顾,探索科技新可能

我们在今年的尾声中回顾本月精彩&#xff0c;开发者们借助创新技术为用户打造温暖的应用体验&#xff0c;展现技术与实用的结合。欢迎您查阅本期月刊&#xff0c;掌握最新动态。 本月看点 精彩看点多多&#xff0c;请上下滑动阅览 01DevFest 北京站和上海站圆满举办&#xff0c…

LinuxC高级day4

作业: 1.思维导图 2.终端输入一个C源文件名(.c结尾)判断文件是否有内容&#xff0c;如果没有内容删除文件&#xff0c;如果有内容编译并执行改文件。 3.终端输入两个文件名&#xff0c;判断哪个文件的时间戳更新

数据中台与数据治理服务方案[50页PPT]

本文概述了数据中台与数据治理服务方案的核心要点。数据中台作为政务服务数据化的核心&#xff0c;通过整合各部门业务系统数据&#xff0c;进行建模与加工&#xff0c;以新数据驱动政府管理效率提升与政务服务能力增强。数据治理则聚焦于解决整体架构问题&#xff0c;确保数据…

MAC环境安装(卸载)软件

MAC环境安装&#xff08;卸载&#xff09;软件 jdknode安装node&#xff0c;并实现不同版本的切换背景 卸载node从node官网下载pkg安装的node卸载用 homebrew 安装的node如果你感觉删的不够干净&#xff0c;可以再细分删除验证删除结果 jdk 1.下载jdk 先去官网下载自己需要的版…

时间序列预测算法---LSTM

文章目录 一、前言1.1、深度学习时间序列一般是几维数据&#xff1f;每个维度的名字是什么&#xff1f;通常代表什么含义&#xff1f;1.2、为什么机器学习/深度学习算法无法处理时间序列数据?1.3、RNN(循环神经网络)处理时间序列数据的思路&#xff1f;1.4、RNN存在哪些问题?…

LinuxC高级day2

1.在家目录下创建目录文件&#xff0c;dir a.dir下创建dir1和dir2 b.把当前目录下的所有文件拷贝到dir1中&#xff0c; c.把当前目录下的所有脚本文件拷贝到dir2中 d.把dir2打包并压缩为dir2.tar.xz e.再把dir2.tar.xz移动到dir1中 f.解压dir1中的压缩包 g.使用tree工具&#x…

14. 日常算法

1. 面试题 02.04. 分割链表 题目来源 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你不需要 保留 每个分区中各节点的初始相对位置。 class Solution { public:ListNo…

ubuntu 如何使用vrf

在Ubuntu或其他Linux系统中&#xff0c;您使用ip命令和sysctl命令配置的网络和内核参数通常是临时的&#xff0c;这意味着在系统重启后这些配置会丢失。为了将这些配置持久化&#xff0c;您需要采取一些额外的步骤。 对于ip命令配置的网络接口和路由&#xff0c;您可以将这些配…

SpringMVC进阶(自定义拦截器以及异常处理)

文章目录 1.自定义拦截器 1.基本介绍 1.说明2.自定义拦截器的三个方法3.流程图 2.快速入门 1.Myinterceptor01.java2.FurnHandler.java3.springDispatcherServlet-servlet.xml配置拦截器4.单元测试 3.拦截特定路径 1.拦截指定路径2.通配符配置路径 4.细节说明5.多个拦截器 1.执…

Mac电脑python多版本环境安装与切换

我当前是python3.9.6环境&#xff0c;需要使用3.9.8环境&#xff0c;通过brew安装3.9.8版本&#xff0c;然后通过pyenv切换环境 步骤 1: 安装 pyenv brew install pyenv brew install pyenv-virtualenv 步骤 2: 安装 Python 3.9.8&#xff08;使用 pyenv 安装指定版本的 Pyth…

【蓝桥杯——物联网设计与开发】拓展模块4 - 脉冲模块

目录 一、脉冲模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;采集原理 &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#xff08;4&#xff09;实验现象 二、脉冲模块接口函数封装 三、踩坑日记 &a…