WPF 进阶特性详解:依赖属性、附加属性、Transform、Effect 与路由事件

news2026/4/27 18:16:20
大家在学习 WPF 的时候前期最容易接触到的是控件、布局和数据绑定但真正把这些能力串起来的其实是 WPF 自己的一整套机制。 比如为什么有些属性能绑定、有些属性能做动画、为什么Grid.Row能写在Button上、为什么一个按钮点击后父级也能收到事件这些问题的答案都藏在 WPF 的“底层特性”里。目录一、WPF 依赖属性1. 什么是依赖属性2. 依赖属性和普通属性有什么区别3. 自定义依赖属性的 3 个步骤4. 实战给自定义控件定义依赖属性5. 依赖属性的回调函数二、WPF 附加属性1. 什么是附加属性2. 附加属性怎么定义3. 实战让 PasswordBox 支持绑定三、WPF Transform 转换1. Transform 是什么2. 四种常见变换2.1 RotateTransform 旋转2.2 ScaleTransform 缩放2.3 SkewTransform 倾斜2.4 TranslateTransform 平移3. 实战TransformGroup 做图片查看器四、WPF Effect 特效1. Effect 是什么2. DropShadowEffect 阴影效果3. BlurEffect 模糊效果五、WPF 路由事件1. 什么是路由事件2. 隧道事件和冒泡事件怎么理解3. 自定义路由事件实战六、总结这篇文章结合实战案例系统梳理 5 个非常重要的知识点依赖属性附加属性Transform 转换Effect 特效路由事件如果你正在做自定义控件、MVVM 绑定、交互动画或者面试里经常被问到 WPF 原理这篇内容基本都绕不开。一、WPF 依赖属性1. 什么是依赖属性依赖属性DependencyProperty是 WPF 属性系统的核心。它不是普通的 .NET 属性包装私有字段而是一种由 WPF 属性系统统一管理的属性机制。它最大的价值在于一个属性的值不再只来自字段本身而是可以同时受到本地值、样式、动画、数据绑定、资源、默认值等多种来源的影响。也正因为如此依赖属性天然支持这些 WPF 高频能力数据绑定样式与模板动画默认值属性变更回调值继承2. 依赖属性和普通属性有什么区别对比项普通 .NET 属性WPF 依赖属性存储方式一般存储在私有字段中由 WPF 属性系统统一管理是否支持绑定不支持支持是否支持动画不支持支持是否支持样式不支持支持变更通知需要手动写可以通过回调处理使用场景普通业务类WPF 控件、可视化对象普通属性写法如下private int length; ​ public int Length { get { return length; } set { length value; } }依赖属性写法如下public int MyProperty { get { return (int)GetValue(MyPropertyProperty); } set { SetValue(MyPropertyProperty, value); } } ​ public static readonly DependencyProperty MyPropertyProperty DependencyProperty.Register( MyProperty, typeof(int), typeof(OwnerClass), new PropertyMetadata(0));3. 自定义依赖属性的 3 个步骤定义一个依赖属性一般分成 3 步定义DependencyProperty静态字段使用DependencyProperty.Register()完成注册用普通属性外壳包装GetValue()和SetValue()其中最关键的一句就是public static readonly DependencyProperty MyPropertyProperty DependencyProperty.Register( MyProperty, typeof(int), typeof(OwnerClass), new PropertyMetadata(0));这 4 个参数分别表示属性名属性类型所属类型元数据默认值、回调函数等4. 实战给自定义控件定义依赖属性下面我们定义一个Widget用户控件用来显示图标、标题和数值。前端 XAMLUserControl x:ClassDemo.Widget xmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:xhttp://schemas.microsoft.com/winfx/2006/xaml x:Nameroot FontSize30 Foreground#666666 BorderBrush#8CDDCD Border BorderBrush{Binding ElementNameroot, PathBorderBrush} Border.Style Style TargetTypeBorder Setter PropertyPadding Value10/ Setter PropertyBackground ValueWhite/ Setter PropertyBorderThickness Value0 3 0 0/ Setter PropertyMargin Value5/ Style.Triggers Trigger PropertyIsMouseOver ValueTrue Setter PropertyBackground Value#F7F9F9/ /Trigger /Style.Triggers /Style /Border.Style Grid Grid.ColumnDefinitions ColumnDefinition/ ColumnDefinition WidthAuto/ /Grid.ColumnDefinitions Grid.RowDefinitions RowDefinition/ RowDefinition/ /Grid.RowDefinitions ​ TextBlock Grid.Row0 Grid.Column0 Text{Binding Value} Foreground{Binding ElementNameroot, PathForeground} FontSize{Binding ElementNameroot, PathFontSize} / ​ TextBlock Grid.Row1 Grid.Column0 Text{Binding Title} Foreground{Binding ElementNameroot, PathForeground} FontSize14 / ​ TextBlock Grid.Row0 Grid.Column1 Grid.RowSpan2 Text{Binding Icon} Foreground{Binding ElementNameroot, PathBorderBrush} FontSize26 VerticalAlignmentCenter/ /Grid /Border /UserControl后台代码public partial class Widget : UserControl { public Widget() { InitializeComponent(); DataContext this; } ​ public string Icon { get { return (string)GetValue(IconProperty); } set { SetValue(IconProperty, value); } } ​ public static readonly DependencyProperty IconProperty DependencyProperty.Register( Icon, typeof(string), typeof(Widget), new PropertyMetadata()); ​ public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } } ​ public static readonly DependencyProperty TitleProperty DependencyProperty.Register( Title, typeof(string), typeof(Widget), new PropertyMetadata(请输入标题)); ​ public string Value { get { return (string)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } ​ public static readonly DependencyProperty ValueProperty DependencyProperty.Register( Value, typeof(string), typeof(Widget), new PropertyMetadata(内容)); }使用时就可以像普通控件一样直接写StackPanel OrientationHorizontal local:Widget Icon Title本年度销售总额 Value38452.21 Width215 Height100/ ​ local:Widget Icon Title系统访问量 Value9985 Foreground#415767 BorderBrush#87BEE4 Width225 Height110/ /StackPanel这就是依赖属性最实用的地方自定义控件既能对外暴露属性又天然支持绑定、样式和后续扩展。5. 依赖属性的回调函数很多时候我们不只是想“存一个值”而是想在值变化后立即执行逻辑这时候就要用到PropertyChangedCallback。例如public static readonly DependencyProperty CountProperty DependencyProperty.Register( Count, typeof(int), typeof(TrayControl), new PropertyMetadata(0, OnCountPropertyChanged)); ​ private static void OnCountPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { var control d as TrayControl; control?.Initialize(); }当Count发生变化时就会自动调用OnCountPropertyChanged。 这类写法非常适合做控件刷新界面重绘数据校验联动其它属性如果你还需要默认值、强制值修正等能力也可以把这些逻辑写到PropertyMetadata中。二、WPF 附加属性1. 什么是附加属性附加属性Attached Property可以理解成某个属性本来不属于这个控件但被另一个类型“附加”到了它身上。最经典的例子就是Grid Button Grid.Row0 Content按钮1/ Button Grid.Row1 Content按钮2/ /Grid这里的Row并不是Button自己定义的属性而是Grid定义出来附加给子元素使用的属性也就是Grid.Row。所以附加属性特别适合这种场景父容器给子元素打标签控件间建立额外关系给原本不支持某种能力的控件补功能2. 附加属性怎么定义Visual Studio 中输入propa按两次Tab就能生成模板。标准写法如下public static int GetMyProperty(DependencyObject obj) { return (int)obj.GetValue(MyPropertyProperty); } ​ public static void SetMyProperty(DependencyObject obj, int value) { obj.SetValue(MyPropertyProperty, value); } ​ public static readonly DependencyProperty MyPropertyProperty DependencyProperty.RegisterAttached( MyProperty, typeof(int), typeof(OwnerClass), new PropertyMetadata(0));和依赖属性相比附加属性最大的区别是使用RegisterAttached()注册通过GetXxx()/SetXxx()访问3. 实战让 PasswordBox 支持绑定PasswordBox的Password并不是依赖属性所以不能像TextBox.Text一样直接绑定。 这也是 WPF 初学者经常会踩的坑。解决思路就是写一个PasswordBoxHelper通过附加属性给PasswordBox搭一座“桥”。先准备一个支持通知的基类public class ObservableObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; ​ public void RaisePropertyChanged([CallerMemberName] string propertyName ) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }再定义实体类public class Person : ObservableObject { private string userName; public string UserName { get { return userName; } set { userName value; RaisePropertyChanged(); } } ​ private string password; public string Password { get { return password; } set { password value; RaisePropertyChanged(); } } }核心桥接代码如下public class PasswordBoxHelper { public static string GetPassword(DependencyObject obj) { return (string)obj.GetValue(PasswordProperty); } ​ public static void SetPassword(DependencyObject obj, string value) { obj.SetValue(PasswordProperty, value); } ​ public static readonly DependencyProperty PasswordProperty DependencyProperty.RegisterAttached( Password, typeof(string), typeof(PasswordBoxHelper), new PropertyMetadata(, OnPasswordPropertyChanged)); ​ private static void OnPasswordPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is PasswordBox passwordBox) { passwordBox.PasswordChanged - PasswordBox_PasswordChanged; passwordBox.PasswordChanged PasswordBox_PasswordChanged; } } ​ private static void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e) { if (sender is PasswordBox passwordBox) { SetPassword(passwordBox, passwordBox.Password); } } } 然后在 XAML 中这样使用 StackPanel Margin80 TextBox Text{Binding Person.UserName, UpdateSourceTriggerPropertyChanged} Width200 Height25/ ​ PasswordBox local:PasswordBoxHelper.Password{Binding Person.Password, ModeTwoWay, UpdateSourceTriggerPropertyChanged} Width200 Height25/ /StackPanel这样就实现了PasswordBox.Password - PasswordBoxHelper.Password - ViewModel.Password这个案例也是附加属性最经典的面试题之一。三、WPF Transform 转换1. Transform 是什么Transform是 WPF 中负责二维图形变换的抽象基类常见子类有 4 个RotateTransform旋转ScaleTransform缩放SkewTransform倾斜TranslateTransform平移如果多个变换要同时使用就交给TransformGroup组合处理。2. 四种常见变换2.1 RotateTransform 旋转Button ContentRotateTransform Button.RenderTransform RotateTransform Angle45 CenterX50 CenterY12.5/ /Button.RenderTransform /Button常用属性Angle旋转角度CenterX旋转中心 X 坐标CenterY旋转中心 Y 坐标2.2 ScaleTransform 缩放Button ContentScaleTransform Button.RenderTransform ScaleTransform ScaleX1.5 ScaleY1.5 CenterX50 CenterY12.5/ /Button.RenderTransform /Button常用属性ScaleXScaleYCenterXCenterY2.3 SkewTransform 倾斜Border Width120 Height120 BackgroundLightBlue Border.RenderTransform SkewTransform AngleX20 AngleY10 CenterX60 CenterY60/ /Border.RenderTransform /Border常用属性AngleXAngleYCenterXCenterY2.4 TranslateTransform 平移Border Width120 Height120 BackgroundLightGreen Border.RenderTransform TranslateTransform X80 Y30/ /Border.RenderTransform /Border常用属性XY3. 实战TransformGroup 做图片查看器如果我们想同时支持图片拖拽和平滑缩放就不能只靠单一变换而是要把ScaleTransform和TranslateTransform组合起来。XAMLCanvas x:Namecanvas BackgroundTransparent MouseWheelcanvas_MouseWheel MouseMovecanvas_MouseMove MouseLeftButtonDowncanvas_MouseLeftButtonDown MouseLeftButtonUpcanvas_MouseLeftButtonUp Image x:Nameimage Source/Images/mm.jpg/ /Canvas后台代码private bool isMouseDown false; private Point mousePoint new Point(0, 0); private TranslateTransform translateTransform new TranslateTransform(); private ScaleTransform scaleTransform new ScaleTransform(); private TransformGroup group new TransformGroup(); ​ public MainWindow() { InitializeComponent(); ​ Loaded (s, e) { group.Children.Add(scaleTransform); group.Children.Add(translateTransform); image.RenderTransform group; ​ var scale Math.Min( canvas.ActualWidth / image.ActualWidth, canvas.ActualHeight / image.ActualHeight); ​ scaleTransform.ScaleX scale; scaleTransform.ScaleY scale; translateTransform.X (canvas.ActualWidth - image.ActualWidth * scale) / 2; }; } ​ private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { isMouseDown true; mousePoint e.GetPosition(canvas); } ​ private void canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { isMouseDown false; } ​ private void canvas_MouseMove(object sender, MouseEventArgs e) { var position e.GetPosition(canvas); if (isMouseDown) { translateTransform.X position.X - mousePoint.X; translateTransform.Y position.Y - mousePoint.Y; mousePoint position; } } ​ private void canvas_MouseWheel(object sender, MouseWheelEventArgs e) { var delta e.Delta * 0.001; var position e.GetPosition(canvas); ​ if (scaleTransform.ScaleX delta 0.1) return; ​ Point inversePoint group.Inverse.Transform(position); ​ scaleTransform.ScaleX delta; scaleTransform.ScaleY delta; translateTransform.X -(inversePoint.X * scaleTransform.ScaleX - position.X); translateTransform.Y -(inversePoint.Y * scaleTransform.ScaleY - position.Y); }这个案例里最值得记住的一点是缩放不是简单改倍率还要同步修正平移量这样才能做到“以鼠标所在位置为中心缩放”。四、WPF Effect 特效1. Effect 是什么Effect是 WPF 里的特效基类常见的两个子类是DropShadowEffect阴影特效BlurEffect模糊特效2. DropShadowEffect 阴影效果给按钮加阴影非常简单Button Content按钮1 Width100 Height50 Button.Effect DropShadowEffect ShadowDepth10 BlurRadius20 ColorGray Direction-45 Opacity1/ /Button.Effect /Button常用属性如下属性作用Color阴影颜色ShadowDepth阴影偏移距离Direction阴影方向BlurRadius模糊半径Opacity透明度在实际项目中这个特效非常适合做卡片悬浮感按钮立体感弹窗层级区分3. BlurEffect 模糊效果模糊效果常用于毛玻璃背景聚焦突出鼠标交互反馈一个简单示例Ellipse Width120 Height120 FillSkyBlue Ellipse.Effect BlurEffect Radius8/ /Ellipse.Effect /Ellipse如果想做动态模糊可以在代码里修改Radiusprivate void grid_MouseMove(object sender, MouseEventArgs e) { Point mousePoint e.GetPosition(this); Point centerPoint new Point(ActualWidth / 2, ActualHeight / 2); ​ double distance Math.Sqrt( Math.Pow(mousePoint.X - centerPoint.X, 2) Math.Pow(mousePoint.Y - centerPoint.Y, 2)); ​ effect.Radius distance / 5; }这样鼠标越远模糊越明显交互感会非常直观。五、WPF 路由事件1. 什么是路由事件WPF 的界面本质上是一棵元素树。 比如下面这段结构Window Border Canvas Button/ Button/ /Canvas /Border /Window当按钮触发事件时这个事件并不一定只在按钮自己身上结束而是可能沿着整棵树传播。 这种“会沿元素树传播”的事件就叫做路由事件。WPF 中常见的路由策略有 3 种Tunnel隧道事件从根节点到事件源常见前缀是PreviewBubble冒泡事件从事件源往父级一路传播Direct直接事件只在事件源本身触发2. 隧道事件和冒泡事件怎么理解如果点击按钮隧道事件路线Window - Border - Canvas - Button冒泡事件路线Button - Canvas - Border - Window看一个隧道事件示例Window PreviewMouseUpWindow_PreviewMouseUp Border PreviewMouseUpBorder_PreviewMouseUp Canvas PreviewMouseUpCanvas_PreviewMouseUp Button PreviewMouseUpButton_PreviewMouseUp Content确定/ /Canvas /Border /Window如果点击按钮输出顺序会是Window对象的隧道事件PreviewMouseUp被触发 Border对象的隧道事件PreviewMouseUp被触发 Canvas对象的隧道事件PreviewMouseUp被触发 Button确定按钮的隧道事件PreviewMouseUp被触发再看冒泡事件Window MouseUpWindow_MouseUp Border MouseUpBorder_MouseUp BackgroundTransparent Canvas MouseUpCanvas_MouseUp BackgroundTransparent Button MouseUpButton_MouseUp Content确定/ /Canvas /Border /Window这里有一个很容易忽略的细节 像Canvas、Border这种控件如果没有背景色哪怕是透明色也可能收不到鼠标事件。3. 自定义路由事件实战除了使用系统自带的路由事件我们也可以注册自己的路由事件。比如给Widget自定义一个“销售完成事件”public static readonly RoutedEvent CompletedEvent EventManager.RegisterRoutedEvent( CompletedEvent, RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Widget)); ​ public event RoutedEventHandler Completed { add { AddHandler(CompletedEvent, value); } remove { RemoveHandler(CompletedEvent, value); } } ​ private void RaiseRoutedEvent() { RoutedEventArgs args new RoutedEventArgs(CompletedEvent, this); RaiseEvent(args); }再结合依赖属性回调做业务判断public double Target { get { return (double)GetValue(TargetProperty); } set { SetValue(TargetProperty, value); } } ​ public static readonly DependencyProperty TargetProperty DependencyProperty.Register( Target, typeof(double), typeof(Widget), new PropertyMetadata(0.0)); ​ public double Value { get { return (double)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } ​ public static readonly DependencyProperty ValueProperty DependencyProperty.Register( Value, typeof(double), typeof(Widget), new PropertyMetadata(0.0, OnValuePropertyChanged)); ​ private static void OnValuePropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is Widget control e.NewValue is double value) { if (value control.Target control.Target ! 0) { control.RaiseRoutedEvent(); } } }前端直接订阅local:Widget Value{Binding ElementNameslider, PathValue} Target1000000 Title第四季度华南市场总销售额统计 CompletedWidget_Completed/后台处理private void Widget_Completed(object sender, RoutedEventArgs e) { Widget widget sender as Widget; listBox.Items.Insert(0, $完成目标销售额{widget.Value}); }这个例子把两个知识点串起来了用依赖属性回调监听值变化用路由事件向外广播业务完成状态在实际项目里这种设计非常适合做自定义控件事件通知业务状态上报父容器统一监听子控件行为六、总结WPF 的很多“高级能力”并不是孤立存在的而是互相配合的依赖属性负责让属性具备绑定、样式、动画和回调能力附加属性负责把一个类型的能力扩展到另一个控件身上Transform 负责视觉变换Effect 负责视觉特效路由事件负责事件传播和控件通信如果你只是写界面可能觉得这些内容有点底层但只要一旦开始做自定义控件、复杂交互、MVVM 架构这些知识几乎都会变成必修课。最后给大家一个学习建议先掌握依赖属性和附加属性因为这两个是 WPF 属性系统的核心。再练习 Transform 和 Effect把界面“做出来”。最后重点理解路由事件把控件之间的通信“串起来”。当你把这 5 个知识点真正吃透之后WPF 里的很多“黑魔法”其实就不神秘了。课后作业简单的后台绑定数据需要注意绑定数据时对属性的定义与数据匹配问题运行展示具体代码XAML:Window x:ClassWpfApp8.MainWindow xmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:xhttp://schemas.microsoft.com/winfx/2006/xaml xmlns:dhttp://schemas.microsoft.com/expression/blend/2008 xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006 xmlns:localclr-namespace:WpfApp8 mc:Ignorabled TitleMainWindow Height450 Width900 Grid Grid.RowDefinitions RowDefinition HeightAuto/ RowDefinition Height*/ /Grid.RowDefinitions TextBlock Text{Binding Model.TimeText} BackgroundSkyBlue FontSize24 ForegroundWhite Margin0 0 0 20/ StackPanel Grid.Row1 OrientationHorizontal Border BackgroundCadetBlue CornerRadius4 Margin5 Width150 Height200 StackPanel Margin20 TextBlock Text⏱ FontSize20 ForegroundWhite/ TextBlock Text汇总 FontSize18 ForegroundWhite Margin0 10 0 20/ TextBlock Text{Binding Model.TotalTasks} FontSize48 ForegroundWhite FontWeightBold/ /StackPanel /Border Border BackgroundLightGreen CornerRadius4 Margin5 Width150 Height200 StackPanel Margin20 TextBlock Text⏱ FontSize20 ForegroundWhite/ TextBlock Text已完成 FontSize18 ForegroundWhite Margin0 10 0 20/ TextBlock Text{Binding Model.CompletedTasks} FontSize48 ForegroundWhite FontWeightBold/ /StackPanel /Border Border BackgroundBlueViolet CornerRadius4 Margin5 Width150 Height200 StackPanel Margin20 TextBlock Text FontSize20 ForegroundWhite/ TextBlock Text完成比例 FontSize18 ForegroundWhite Margin0 10 0 20/ TextBlock Text{Binding Model.CompletionRate} FontSize48 ForegroundWhite FontWeightBold/ /StackPanel /Border Border BackgroundOrange CornerRadius4 Margin5 Width150 Height200 StackPanel Margin20 TextBlock Text FontSize20 ForegroundWhite/ TextBlock Text备忘录 FontSize18 ForegroundWhite Margin0 10 0 20/ TextBlock Text{Binding Model.MemoCount} FontSize48 ForegroundWhite FontWeightBold/ /StackPanel /Border /StackPanel /Grid /WindowModel.csusing System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace WpfApp8 { public class Model { private string _timeText; private int _totalTasks; private int _completedTasks; private string _completionRate; private int _memoCount; public string TimeText { get _timeText; set _timeText value; } public int TotalTasks { get _totalTasks; set _totalTasks value; } public int CompletedTasks { get _completedTasks; set _completedTasks value; } public string CompletionRate { get _completionRate; set _completionRate value; } public int MemoCount { get _memoCount; set _memoCount value; } } }TaskView.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel; using System.Runtime.CompilerServices; namespace WpfApp8 { public class TaskView { public Model Model { get; set; } public TaskView() { Model new Model(); Model.TimeText $你好{DateTime.Now:yyyy年M月d日dddd}; Model.TotalTasks 27; Model.CompletedTasks 24; Model.CompletionRate 89%; Model.MemoCount 13; } } }MainWindow.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp8 { /// summary /// MainWindow.xaml 的交互逻辑 /// /summary public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.DataContext new TaskView(); } } }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…