WPF进阶 | 深入 WPF 依赖项属性:理解其强大功能与应用场景


WPF进阶 | 深入 WPF 依赖项属性:理解其强大功能与应用场景
- 前言
- 一、依赖项属性基础概念
- 1.1 什么是依赖项属性
- 1.2 依赖项属性与 CLR 属性的区别
- 1.3 依赖项属性的定义与注册
- 二、依赖项属性的原理深入剖析
- 2.1 依赖项属性系统的工作机制
- 2.2 元数据(Metadata)的作用
- 三、依赖项属性的应用场景
- 3.1 数据绑定
- 3.2 样式与模板
- 3.3 动画
- 3.4 自定义控件开发
- 四、依赖项属性的高级应用
- 4.1 附加属性(Attached Properties)
- 4.2 依赖项属性的继承与重写
- 4.3 依赖项属性在复杂界面布局中的应用
- 五、依赖项属性的性能优化与常见问题处理
- 5.1 性能优化
- 5.2 常见问题处理
- 六、总结
- 结束语
- 优质源码分享
WPF进阶 | 深入 WPF 依赖项属性:理解其强大功能与应用场景,在 Windows Presentation Foundation(WPF)开发中,依赖项属性是一个核心且强大的特性,它为构建灵活、可扩展的用户界面提供了关键支持。理解并熟练运用依赖项属性,对于开发高效、健壮的 WPF 应用程序至关重要。本文将深入探讨 WPF 依赖项属性,通过丰富的代码示例和对关键概念的详细解释,帮助读者全面掌握这一重要特性及其应用场景。
前言
在数字浪潮汹涌澎湃的时代,程序开发宛如一座神秘而宏伟的魔法城堡,矗立在科技的浩瀚星空中。代码的字符,似那闪烁的星辰,按照特定的轨迹与节奏,组合、交织、碰撞,即将开启一场奇妙且充满无限可能的创造之旅。当空白的文档界面如同深邃的宇宙等待探索,程序员们则化身无畏的星辰开拓者,指尖在键盘上轻舞,准备用智慧与逻辑编织出足以改变世界运行规则的程序画卷,在 0 和 1 的二进制世界里,镌刻下属于人类创新与突破的不朽印记。
在当今数字化时代,桌面应用程序的用户界面(UI)设计至关重要,它直接影响着用户体验与产品的竞争力。而 WPF(Windows Presentation Foundation)作为微软推出的一款强大的 UI 框架,其布局系统更是构建精美界面的核心要素。WPF 布局系统为开发者提供了丰富多样的布局方式,能够轻松应对各种复杂的界面设计需求,无论是简洁明了的工具软件,还是功能繁杂的企业级应用,都能借助其打造出令人惊艳的视觉效果与流畅的交互体验。
WPF从入门到精通专栏,旨在为读者呈现一条从对 WPF(Windows Presentation Foundation)技术懵懂无知到精通掌握的学习路径。首先从基础入手,介绍 WPF 的核心概念,涵盖其独特的架构特点、开发环境搭建流程,详细解读布局系统、常用控件以及事件机制等基础知识,帮助初学者搭建起对 WPF 整体的初步认知框架。随着学习的深入,进阶部分聚焦于数据绑定、样式模板、动画特效等关键知识点,进一步拓展 WPF 开发的能力边界,使开发者能够打造出更为个性化、交互性强的桌面应用界面。高级阶段则涉及自定义控件开发、MVVM 设计模式应用、多线程编程等深层次内容,助力开发者应对复杂的业务需求,构建大型且可维护的应用架构。同时,通过实战项目案例解析,展示如何将所学知识综合运用到实际开发中,从需求分析到功能实现再到优化测试,全方位积累实践经验。此外,还探讨了性能优化、与其他技术集成以及安全机制等拓展性话题,让读者对 WPF 技术在不同维度有更深入理解,最终实现对 WPF 技术的精通掌握,具备独立开发高质量桌面应用的能力。
🛕 点击进入WPF从入门到精通专栏

一、依赖项属性基础概念
1.1 什么是依赖项属性
依赖项属性是一种特殊类型的属性,它的值不仅取决于自身的赋值,还可能依赖于其他因素,如数据绑定、样式设置、动画等。与传统的 CLR 属性不同,依赖项属性通过 WPF 的依赖项属性系统进行管理,这使得它们具有很多独特的功能和优势。
例如,在一个简单的 WPF 按钮中,Button的Background属性就是一个依赖项属性。我们可以通过直接赋值来设置按钮的背景颜色,也可以通过数据绑定将背景颜色与某个数据源的值关联起来,还可以使用样式来统一设置按钮的背景颜色,甚至可以通过动画来动态改变按钮的背景颜色。
1.2 依赖项属性与 CLR 属性的区别
存储方式:CLR 属性的值直接存储在对象的字段中,而依赖项属性的值存储在一个独立的属性存储机制中,称为依赖项对象的属性存储区。这种分离的存储方式使得依赖项属性能够支持更多的功能,如数据绑定、样式设置等。
功能特性:CLR 属性主要用于简单的数据存储和访问,而依赖项属性具有更丰富的功能,包括:
值继承:依赖项属性可以在元素树中进行值继承。例如,在一个包含多个子控件的容器中,如果容器设置了某个依赖项属性的值,其子控件可以自动继承该值,除非子控件显式地设置了不同的值。
数据绑定:依赖项属性天生支持数据绑定,这使得我们可以方便地将界面元素的属性与数据源进行绑定,实现数据的双向同步。
样式设置:依赖项属性可以通过样式进行统一设置和修改,从而实现界面的统一风格和主题切换。
动画支持:依赖项属性可以参与动画,通过改变属性值随时间的变化来创建动态的视觉效果。
1.3 依赖项属性的定义与注册
在 WPF 中,定义一个依赖项属性需要以下几个步骤:
定义依赖项属性字段:首先,需要在类中定义一个静态的DependencyProperty字段,用于标识这个依赖项属性。例如:
public class MyControl : Control
{public static readonly DependencyProperty MyPropertyProperty =DependencyProperty.Register("MyProperty", typeof(string), typeof(MyControl), new PropertyMetadata("默认值"));
}
在这个例子中,MyPropertyProperty是一个静态的DependencyProperty字段,Register方法用于注册这个依赖项属性。Register方法的第一个参数是属性的名称(MyProperty),第二个参数是属性的类型(typeof(string)),第三个参数是拥有该属性的类的类型(typeof(MyControl)),第四个参数是属性的元数据,这里使用PropertyMetadata来设置属性的默认值为 “默认值”。
定义 CLR 属性包装器:为了方便在代码中使用依赖项属性,通常会定义一个 CLR 属性包装器,通过这个包装器来访问和设置依赖项属性的值。例如:
public string MyProperty
{get { return (string)GetValue(MyPropertyProperty); }set { SetValue(MyPropertyProperty, value); }
}
在这个 CLR 属性包装器中,GetValue方法用于获取依赖项属性的值,SetValue方法用于设置依赖项属性的值。
二、依赖项属性的原理深入剖析
2.1 依赖项属性系统的工作机制
WPF 的依赖项属性系统是一个复杂而高效的机制,它负责管理依赖项属性的各种行为。当获取或设置一个依赖项属性的值时,依赖项属性系统会按照一定的规则来确定最终的值。这个规则涉及到多个因素,包括:
本地值:如果在代码中直接对依赖项属性进行了赋值,这个值就是本地值。本地值具有最高的优先级,会覆盖其他来源的值。
继承值:如果依赖项属性支持值继承,并且在当前元素的父元素中设置了该属性的值,当前元素会继承这个值,除非它自己设置了本地值。
默认值:在注册依赖项属性时,可以通过PropertyMetadata设置默认值。如果没有其他值来源,依赖项属性会使用默认值。
数据绑定值:如果依赖项属性与某个数据源进行了绑定,数据绑定的值会参与最终值的确定。数据绑定的值的优先级低于本地值,但高于继承值和默认值。
样式和模板值:通过样式和模板设置的依赖项属性值也会影响最终的值。样式和模板值的优先级低于本地值和数据绑定值,但高于继承值和默认值。
例如,假设我们有一个Button控件,其Background属性是一个依赖项属性。如果我们在代码中直接设置了Button.Background = Brushes.Red;,这就是本地值,按钮的背景颜色将是红色。如果没有设置本地值,而按钮的父容器设置了Background属性,按钮会继承父容器的背景颜色。如果既没有本地值也没有继承值,Button会使用Background属性的默认值。如果Button.Background与某个数据源进行了绑定,并且数据源的值发生了变化,按钮的背景颜色会根据绑定的值进行更新。
2.2 元数据(Metadata)的作用
在注册依赖项属性时,PropertyMetadata用于定义依赖项属性的元数据,它包含了很多重要的信息,如:
默认值:前面已经提到,通过PropertyMetadata可以设置依赖项属性的默认值。
属性更改回调:可以定义一个回调方法,当依赖项属性的值发生变化时,会自动调用这个回调方法。例如:
public static readonly DependencyProperty MyPropertyProperty =DependencyProperty.Register("MyProperty", typeof(string), typeof(MyControl),new PropertyMetadata("默认值", OnMyPropertyChanged));private static void OnMyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{MyControl control = (MyControl)d;string oldValue = (string)e.OldValue;string newValue = (string)e.NewValue;// 在这里处理属性值变化的逻辑,例如更新界面显示control.UpdateUI(oldValue, newValue);
}
在这个例子中,OnMyPropertyChanged是属性更改回调方法,当MyProperty属性的值发生变化时,会传入DependencyObject(即拥有该属性的对象)和DependencyPropertyChangedEventArgs(包含旧值和新值等信息),我们可以在这个方法中处理属性值变化的逻辑。
强制值回调:在某些情况下,可能需要在设置依赖项属性值之前对值进行验证或修正,这时可以使用强制值回调。例如:
public static readonly DependencyProperty MyPropertyProperty =DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),new PropertyMetadata(0, null, CoerceMyProperty));private static object CoerceMyProperty(DependencyObject d, object baseValue)
{int value = (int)baseValue;if (value < 0){value = 0;}else if (value > 100){value = 100;}return value;
}
在这个例子中,CoerceMyProperty是强制值回调方法,当设置MyProperty属性的值时,如果值小于 0 或大于 100,会将其修正为 0 或 100。
三、依赖项属性的应用场景
3.1 数据绑定
数据绑定是依赖项属性最常见的应用场景之一。通过数据绑定,我们可以将界面元素的属性与数据源进行关联,实现数据的双向同步。例如,我们有一个包含TextBox和Button的窗口,TextBox用于输入文本,Button用于显示输入的文本:
<Window x:Class="WpfApp1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Data Binding Example" Height="350" Width="525"><Window.DataContext><local:MainViewModel/></Window.DataContext><Grid><TextBox Text="{Binding UserInput}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200"/><Button Content="{Binding UserInput}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,50,0,0"/></Grid>
</Window>
在后台代码中,定义MainViewModel类:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;namespace WpfApp1
{public class MainViewModel : INotifyPropertyChanged{private string _userInput;public string UserInput{get { return _userInput; }set{_userInput = value;OnPropertyChanged();}}public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}
在这个例子中,TextBox的Text属性和Button的Content属性都绑定到了MainViewModel的UserInput属性。当用户在TextBox中输入文本时,UserInput属性的值会更新,同时Button的Content也会随之更新,实现了数据的双向同步。
3.2 样式与模板
依赖项属性在样式和模板中起着关键作用。通过样式,我们可以统一设置一组控件的外观和行为;通过模板,我们可以自定义控件的可视化结构。例如,我们可以定义一个按钮的样式,设置按钮的背景颜色、字体大小等依赖项属性:
<Window.Resources><Style x:Key="MyButtonStyle" TargetType="Button"><Setter Property="Background" Value="Blue"/><Setter Property="Foreground" Value="White"/><Setter Property="FontSize" Value="14"/></Style>
</Window.Resources>
<Grid><Button Content="Click Me" Style="{StaticResource MyButtonStyle}"/>
</Grid>
在这个例子中,MyButtonStyle样式通过Setter设置了Button的Background、Foreground和FontSize等依赖项属性,所有应用该样式的按钮都会具有相同的外观。
对于模板,我们可以通过依赖项属性来控制模板中的元素。例如,定义一个自定义的ProgressBar模板,通过依赖项属性来控制进度条的进度:
<ControlTemplate x:Key="MyProgressBarTemplate" TargetType="ProgressBar"><Grid><Rectangle Fill="Gray" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/><Rectangle Fill="Green" Width="{Binding Value, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ProgressConverter}}" Height="{TemplateBinding Height}"/></Grid>
</ControlTemplate>
在这个模板中,Rectangle的Width属性通过TemplateBinding绑定到ProgressBar的Value属性(经过ProgressConverter转换),实现了根据ProgressBar的进度值来动态改变绿色矩形的宽度,从而显示进度条的进度。
3.3 动画
依赖项属性是实现 WPF 动画的基础。通过动画,我们可以改变依赖项属性的值随时间的变化,创建出各种动态的视觉效果。例如,我们可以创建一个动画,让按钮在点击时逐渐放大:
<Window.Resources><Storyboard x:Key="ButtonGrowStoryboard"><DoubleAnimationStoryboard.TargetName="MyButton"Storyboard.TargetProperty="Width"From="100" To="150" Duration="0:0:0.5"/></Storyboard>
</Window.Resources>
<Grid><Button x:Name="MyButton" Content="Click Me" HorizontalAlignment="Center" VerticalAlignment="Center"><Button.Triggers><EventTrigger RoutedEvent="Button.Click"><BeginStoryboard Storyboard="{StaticResource ButtonGrowStoryboard}"/></EventTrigger></Button.Triggers></Button>
</Grid>
在这个例子中,DoubleAnimation动画作用于Button的Width依赖项属性,从 100 逐渐变化到 150,持续时间为 0.5 秒。当按钮被点击时,触发动画,按钮的宽度会逐渐增加,实现放大效果。
3.4 自定义控件开发
在自定义控件开发中,依赖项属性是必不可少的。通过定义依赖项属性,我们可以为自定义控件提供丰富的功能和可定制性。例如,我们创建一个自定义的NumericUpDown控件,用于输入和调整数值:
public class NumericUpDown : Control
{public static readonly DependencyProperty ValueProperty =DependencyProperty.Register("Value", typeof(int), typeof(NumericUpDown),new PropertyMetadata(0, OnValueChanged));public int Value{get { return (int)GetValue(ValueProperty); }set { SetValue(ValueProperty, value); }}private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){NumericUpDown control = (NumericUpDown)d;int oldValue = (int)e.OldValue;int newValue = (int)e.NewValue;// 在这里处理数值变化的逻辑,例如更新显示control.UpdateDisplay(oldValue, newValue);}
}
在 XAML 中使用这个自定义控件:
<local:NumericUpDown Value="5" HorizontalAlignment="Left" VerticalAlignment="Top"/>
在这个例子中,NumericUpDown控件定义了一个Value依赖项属性,用于存储当前的数值。当Value属性的值发生变化时,会调用OnValueChanged回调方法,我们可以在这个方法中处理数值变化的逻辑,如更新控件的显示。
四、依赖项属性的高级应用
4.1 附加属性(Attached Properties)
附加属性是一种特殊的依赖项属性,它可以附加到任何依赖项对象上,而不需要在该对象的类中预先定义。附加属性通常用于在不修改现有类的情况下为其添加额外的功能。例如,Grid的Row和Column属性就是附加属性,它们可以附加到Grid的子控件上,用于指定子控件在Grid中的位置:
<Grid><Button Content="Button 1" Grid.Row="0" Grid.Column="0"/><Button Content="Button 2" Grid.Row="0" Grid.Column="1"/>
</Grid>
在代码中定义附加属性的方式与普通依赖项属性类似,只是注册方法略有不同。例如,定义一个自定义的附加属性MyAttachedProperty:
public class MyAttachedProperties
{public static readonly DependencyProperty MyAttachedPropertyProperty =DependencyProperty.RegisterAttached("MyAttachedProperty", typeof(string), typeof(MyAttachedProperties),new PropertyMetadata(null));public static void SetMyAttachedProperty(DependencyObject element, string value){element.SetValue(MyAttachedPropertyProperty, value);}public static string GetMyAttachedProperty(DependencyObject element){return (string)element.GetValue(MyAttachedPropertyProperty);}
}
在 XAML 中使用这个附加属性:
<Button Content="My Button" local:MyAttachedProperties.MyAttachedProperty="Some Value"/>
4.2 依赖项属性的继承与重写
依赖项属性支持继承和重写。当一个类继承自另一个类时,它会继承父类的依赖项属性。如果子类需要修改依赖项属性的行为,可以通过重写元数据来实现。例如,假设我们有一个BaseControl类,定义了一个MyProperty依赖项属性:
public class BaseControl : Control
{public static readonly DependencyProperty MyPropertyProperty =DependencyProperty.Register("MyProperty", typeof(string), typeof(BaseControl),new PropertyMetadata("Base Value"));public string MyProperty{get { return (string)GetValue(MyPropertyProperty); }set { SetValue(MyPropertyProperty, value); }}
}
假设我们有一个自定义的AgeInput控件,用于输入年龄,要求年龄必须是大于 0 且小于 150 的整数。可以这样实现:
public class AgeInput : Control
{public static readonly DependencyProperty AgeProperty =DependencyProperty.Register("Age", typeof(int), typeof(AgeInput),new PropertyMetadata(0, OnAgeChanged, CoerceAge));public int Age{get { return (int)GetValue(AgeProperty); }set { SetValue(AgeProperty, value); }}private static void OnAgeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){int oldAge = (int)e.OldValue;int newAge = (int)e.NewValue;// 这里可以添加一些年龄变化时的额外逻辑,比如更新界面提示AgeInput control = (AgeInput)d;control.UpdateAgeDisplay(oldAge, newAge);}private static object CoerceAge(DependencyObject d, object baseValue){int value = (int)baseValue;if (value <= 0){value = 1;// 可以添加提示信息,告知用户输入不符合要求}else if (value >= 150){value = 149;// 可以添加提示信息,告知用户输入不符合要求}return value;}
}
在 XAML 中使用该控件:
<local:AgeInput Age="25" HorizontalAlignment="Left" VerticalAlignment="Top"/>
在这个示例中,CoerceAge方法作为强制值回调,会在设置Age属性值时检查输入值是否在合理范围内。如果不在,会将其修正为合理的值,确保了数据的有效性。
4.3 依赖项属性在复杂界面布局中的应用
在构建复杂的用户界面时,依赖项属性的灵活性和强大功能得以充分体现。例如,在一个具有动态布局的多文档界面(MDI)应用中,每个文档窗口的大小、位置等属性都可以定义为依赖项属性。
public class DocumentWindow : Window
{public static readonly DependencyProperty WindowWidthProperty =DependencyProperty.Register("WindowWidth", typeof(double), typeof(DocumentWindow),new PropertyMetadata(400.0));public static readonly DependencyProperty WindowHeightProperty =DependencyProperty.Register("WindowHeight", typeof(double), typeof(DocumentWindow),new PropertyMetadata(300.0));public double WindowWidth{get { return (double)GetValue(WindowWidthProperty); }set { SetValue(WindowWidthProperty, value); }}public double WindowHeight{get { return (double)GetValue(WindowHeightProperty); }set { SetValue(WindowHeightProperty, value); }}// 可以添加更多依赖项属性,如窗口位置等
}
在 XAML 中:
<local:DocumentWindow WindowWidth="500" WindowHeight="400" Title="文档1"/>
通过这种方式,可以方便地在 XAML 中配置每个文档窗口的大小,也可以通过数据绑定或其他方式动态改变这些属性,实现灵活的界面布局。
五、依赖项属性的性能优化与常见问题处理
5.1 性能优化
减少不必要的属性更改通知:依赖项属性的属性更改回调会在属性值变化时被调用,如果频繁触发属性更改通知,可能会影响性能。在代码中,尽量批量处理属性值的变化,而不是每次小幅度更改都触发通知。例如,在更新一个包含多个依赖项属性的自定义控件时,可以先设置一个标志位,在所有属性都更新完成后,再统一触发属性更改通知。
合理使用默认值:依赖项属性的默认值设置对性能也有一定影响。如果默认值设置得合理,可以减少不必要的计算和赋值操作。例如,对于一个在大多数情况下都显示为黑色的文本控件,将Foreground属性的默认值设置为Brushes.Black,避免在每个实例创建时都进行额外的初始化操作。
避免过度依赖值继承:虽然依赖项属性的值继承机制很方便,但在大型复杂的元素树中,过度使用值继承可能会导致性能下降。因为值继承需要在元素树中向上或向下查找属性值,这会增加查找的时间开销。尽量在必要的情况下使用值继承,并且注意元素树的层级深度。
5.2 常见问题处理
属性值不更新问题:有时会遇到依赖项属性的值在代码中修改了,但界面上没有及时更新的情况。这可能是因为没有正确触发属性更改通知,或者数据绑定的更新模式设置不正确。确保在属性值变化时,正确调用OnPropertyChanged方法(如果使用INotifyPropertyChanged接口),并且检查数据绑定的UpdateSourceTrigger属性,确保其设置符合需求。
依赖项属性冲突:在复杂的项目中,可能会出现不同的库或模块定义了相同名称的依赖项属性,导致冲突。为了避免这种情况,在定义依赖项属性时,尽量使用唯一的命名空间或前缀。例如,在自定义控件库中,使用库的名称作为依赖项属性名称的前缀,如MyLibrary_MyProperty。
附加属性的使用误区:在使用附加属性时,容易出现将附加属性添加到不支持的对象上,或者在获取和设置附加属性时出现类型错误。在使用附加属性之前,仔细检查目标对象是否支持该附加属性,并且在代码中进行必要的类型检查和转换。
六、总结
WPF 依赖项属性是 WPF 框架中一个极其强大且核心的特性,它为开发者提供了构建灵活、可扩展用户界面的有力工具。通过本文对依赖项属性的基础概念、原理、应用场景、高级应用以及性能优化和常见问题处理的全面深入探讨,读者应该对依赖项属性有了全面而深入的理解。在实际的 WPF 应用开发中,根据具体的需求,合理、巧妙地运用依赖项属性,可以显著提高代码的质量和可维护性,打造出更加高效、健壮的用户界面。随着 WPF 技术的不断发展和应用场景的日益丰富,依赖项属性的应用也将不断拓展和深化,开发者需要持续关注和学习,以充分发挥其强大功能。
结束语
展望未来,WPF 布局系统依然有着广阔的发展前景。随着硬件技术的不断革新,如高分辨率屏幕、折叠屏设备的日益普及,WPF 布局系统有望进一步强化其自适应能力,为用户带来更加流畅、一致的体验。在应对高分辨率屏幕时,能够更加智能地缩放和布局元素,确保文字清晰可读、图像不失真;对于折叠屏设备,可动态调整布局结构,充分利用多屏空间,实现无缝切换。
性能优化方面,微软及广大开发者社区将持续努力,进一步降低复杂布局的计算开销,提高布局更新的效率,使得 WPF 应用在处理大规模数据、动态界面时依然能够保持高效响应。通过改进算法、优化内存管理等手段,让 WPF 布局系统在性能上更上一层楼。
亲爱的朋友,无论前路如何漫长与崎岖,都请怀揣梦想的火种,因为在生活的广袤星空中,总有一颗属于你的璀璨星辰在熠熠生辉,静候你抵达。
愿你在这纷繁世间,能时常收获微小而确定的幸福,如春日微风轻拂面庞,所有的疲惫与烦恼都能被温柔以待,内心永远充盈着安宁与慰藉。
至此,文章已至尾声,而您的故事仍在续写,不知您对文中所叙有何独特见解?期待您在心中与我对话,开启思想的新交流。

优质源码分享
-
【百篇源码模板】html5各行各业官网模板源码下载
-
【模板源码】html实现酷炫美观的可视化大屏(十种风格示例,附源码)
-
【VUE系列】VUE3实现个人网站模板源码
-
【HTML源码】HTML5小游戏源码
-
【C#实战案例】C# Winform贪吃蛇小游戏源码

💞 关注博主 带你实现畅游前后端
🏰 大屏可视化 带你体验酷炫大屏
💯 神秘个人简介 带你体验不一样得介绍
🎀 酷炫邀请函 带你体验高大上得邀请
① 🉑提供云服务部署(有自己的阿里云);
② 🉑提供前端、后端、应用程序、H5、小程序、公众号等相关业务;
如🈶合作请联系我,期待您的联系。
注:本文撰写于CSDN平台,作者:xcLeigh(所有权归作者所有) ,https://blog.csdn.net/weixin_43151418,如果相关下载没有跳转,请查看这个地址,相关链接没有跳转,皆是抄袭本文,转载请备注本文原地址。
亲,码字不易,动动小手,欢迎 点赞 ➕ 收藏,如 🈶 问题请留言(评论),博主看见后一定及时给您答复,💌💌💌
原文地址:https://blog.csdn.net/weixin_43151418/article/details/145325587(防止抄袭,原文地址不可删除)
相关文章:
WPF进阶 | 深入 WPF 依赖项属性:理解其强大功能与应用场景
WPF进阶 | 深入 WPF 依赖项属性:理解其强大功能与应用场景 前言一、依赖项属性基础概念1.1 什么是依赖项属性1.2 依赖项属性与 CLR 属性的区别1.3 依赖项属性的定义与注册 二、依赖项属性的原理深入剖析2.1 依赖项属性系统的工作机制2.2 元数据(Metadata…...
关于 IoT DC3 中设备(Device)的理解
在物联网系统中,设备(Device)是一个非常宽泛的概念,它可以指代任何能够接入系统并进行数据交互的实体。包括但不限于手机、电脑、服务器、网关、硬件设备甚至是某些软件程序等所有能接入到该平台的媒介。 内容 定义 目的 示例 …...
从 0 开始本地部署 DeepSeek:详细步骤 + 避坑指南 + 构建可视化(安装在D盘)
个人主页:chian-ocean 前言: 随着人工智能技术的迅速发展,大语言模型在各个行业中得到了广泛应用。DeepSeek 作为一个新兴的 AI 公司,凭借其高效的 AI 模型和开源的优势,吸引了越来越多的开发者和企业关注。为了更好地…...
Uniapp 获取定位详解:从申请Key到实现定位功能
文章目录 前言一、申请定位所需的 Key1.1 注册高德开发者账号1.2 创建应用1.3 添加 Key 二、在 Uniapp 中配置定位功能2.1 引入高德地图 SDK2.2 获取定位权限 三、实现定位功能3.1 使用 uni.getLocation 获取位置3.2 处理定位失败的情况3.3 持续定位3.4 停止持续定位 四、总结 …...
【6】阿里面试题整理
[1]. ThreadLocal原理 ThreadLocal提供了一种线程隔离的机制,使得每个线程拥有自己独立的变量副本。 它的底层实现是ThreadLocalMap,以ThreadLocal对象为键,变量副本为值的键值对。 为了避免内存泄漏,ThreadLocalMap的Key使用了…...
Spring系统学习——持续更新
spring概述 1.轻量级的开源的JAVAEE框架 2.解决企业应用开发的复杂性 3.两大核心 :IOC(控制反转)和AOP(面向切面) 4.Spring特点: 1.方便解耦,简化开发。2.Aop编程支持3.方便程序测试4.方便和其…...
【自学笔记】机器学习基础知识点总览-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 机器学习重点知识点总览一、机器学习基础概念二、机器学习理论基础三、机器学习算法1. 监督学习2. 无监督学习3. 强化学习 四、机器学习处理流程五、机器学习常见问…...
QT笔记——QRadioButton
文章目录 1、概要2、实际的应用2.1、创建多个QRadioButton,只可同时选中其中一个,点击后实现对应的槽函数 1、概要 实现QRadioButton相关的应用;2、实际的应用 2.1、创建多个QRadioButton,只可同时选中其中一个,点击后实现对应的槽函数 创建…...
微服务面试题:远程调用
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
共享设备管理难?MDM助力Kiosk模式一键部署
目录 1. 简化设备部署与配置:实现一键式部署 2. 自动化应用更新与内容推送:确保设备始终保持最新状态 3. 权限控制与设备安全:防止滥用与数据泄露 4. 远程管理与故障诊断:保障设备长期稳定运行 5. 数据分析与报告:…...
C++17 中的 std::reduce:详细教程
文章目录 1. 简介2. 函数签名3. 使用场景3.1 简单的累加操作3.2 自定义归并操作3.3 并行计算的性能优势 4. 注意事项4.1 归并操作的结合律和交换律4.2 默认值的使用 5. 总结 1. 简介 std::reduce 是 C17 标准库中引入的一个算法,用于对范围内的元素进行归并操作。它…...
Navicat导入海量Excel数据到数据库(简易介绍)
目录 前言正文 前言 此处主要作为科普帖进行记录 原先Java处理海量数据的导入时,由于接口超时,数据处理不过来,后续转为Navicat Navicat 是一款功能强大的数据库管理工具,支持多种数据库系统(如 MySQL、PostgreSQL、…...
【Map vs Set】:Java数据存储的“双子星”对决
个人主页:♡喜欢做梦 欢迎 👍点赞 ➕关注 ❤️收藏 💬评论 目录 🍰一、搜索 🍮1.概念 🍮2.模型 🍰二、Map 🍨1.什么是Map? 🍨2.Map的实例化 &…...
储能能量管理监测系统在储能物联网中的应用优势
安科瑞刘鸿鹏 摘要 本文探讨了微电网能量管理系统在现代储能物联网中的应用。随着能源危机和新能源技术的发展,微电网技术成为利用新能源电力的重要方向。微电网能量管理系统通过实时监控、智能预测、协调控制和经济调度等功能,优化能源使用࿰…...
用户管理中心--注册登录功能的设计
文章目录 1.定义接口2.注册逻辑的实现2.1引入依赖2.2注册逻辑2.3测试方法 3.登录逻辑的实现3.1接口的定义与实现3.2记录用户的登录态3.3脱敏处理 1.定义接口 在userService这个接口里面定义我们的userRegister方法,表示的是我们的用户的注册的相关的逻辑࿱…...
【删除tomcat默认管理控制台】
停止Tomcat: ./catalina.sh stop 删除管理控制台应用: 进入Tomcat的webapps目录: cd /path/to/tomcat/webapps List item 删除manager和host-manager文件夹: rm -rf manager host-manager 启动Tomcat: ./catali…...
Java虚拟机面试题:JVM调优
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
MySQL 插入替换语句(replace into statement)
我们日常使用 insert into 语句向表中插入数据时,一定遇到过主键或唯一索引冲突的情况,MySQL的反应是报错并停止执行后续的语句,而replace into语句可以实现强制插入。 文章目录 一、replace into 语句简介1.1 基本用法1.2 使用set语句 二、注…...
基于单片机的多功能热水器设计(论文+源码)
2.1系统方案设计 基于单片机的多功能热水器系统,其系统框图如图2.1所示。主要采用了DS18B20温度传感器,HC-SR04超声波模块,STC89C52单片机,液晶,继电器等来构成整个系统。硬件上主要通过温度传感器进行水温的检测&…...
DeepSeek R1本地部署 DeepSeek Api接口调用 java go版本
1、本地ollama的API接口 接着上一章所本地部署deepseek,这一章我们调用ollama api 对应的curl: curl --request POST \--url http://localhost:11434/api/generate \--header Accept: */* \--header Accept-Encoding: gzip, deflate, br \--header Con…...
使用python脚本提取html网页上的所有文本信息
你可以使用 BeautifulSoup 库来提取 HTML 网页上的所有文本信息。以下是一个示例脚本: 步骤 安装 beautifulsoup4 和 requests(如果尚未安装): pip install beautifulsoup4 requestsPython 脚本: import requests fro…...
基于SSM+uniapp的购药小程序+LW示例参考
1.项目介绍 系统角色:管理员、普通用户功能模块:用户管理、商家管理、药品管理、药品信息管理、发票管理、订单管理、收藏管理、购物车、充值、下单等技术选型:SSM,Vue(后端管理web),uniapp等测…...
YOLO11网络结构以及改进1
YOLO11 1.YOLO11网络结构图在哪里?2.对应的网络结构图3.每一个模块详解3.1 Conv模块3.2关于卷积模块3.3 关于给各个模块指定参数的细节 4.加入CBAM 1.YOLO11网络结构图在哪里? 2.对应的网络结构图 3.每一个模块详解 3.1 Conv模块 位置:ultr…...
AI 编程私有化部署,在使用 cline 时,可能无法避免私隐的泄漏问题
摘录:Cline Privacy Policy https://github.com/cline/cline/blob/main/docs/PRIVACY.md Key Points Cline operates entirely client-side as a VS Code extensionNo code or data is collected, stored, or transmitted to Clines servers 问题是:…...
计算机视觉-局部特征
一、局部特征 1.1全景拼接 先用RANSAC估计出变换,就可以拼接两张图片 ①提取特征 ②匹配特征 ③拼接图像 1.2 点的特征 怎么找到对应点?(才能做点对应关系RANSAC) :特征检测 我们希望找到的点具有的特征有什么特…...
数据结构:Map Set(一)
目录 一、搜索树 1、概念 2、查找 3、插入 4、删除 二、搜索 1、概念及场景 2、模型 (1)纯key模型 (2)Key-Value模型 三、Map的使用 1、什么是Map? 2、Map的常用方法 (1)V put(K …...
关闭浏览器安全dns解决访问速度慢的问题
谷歌浏览器加载速度突然变慢了?检查安全DNS功能(DoH)是否被默认开启。 谷歌浏览器在去年已经推出安全DNS功能(即DoH) , 启用此功能后可以通过加密的DNS增强网络连接安全性。例如查询请求被加密后网络运营商将无法嗅探用户访问的地址,因此对于增强用户的…...
C语言-章节 4:函数的定义与声明 ——「神秘法术的卷轴」
少年和 Inta 成功通过运算符与表达式的考验后,继续在函数城堡中探索。他们沿着一条闪烁着幽光的走廊前行,走廊两侧的墙壁上刻满了奇异的符号,仿佛在诉说着古老的编程秘密。终于,他们来到了一间神秘的房间,房间中央悬浮…...
47.实验室管理系统(基于SSM和html的Java项目)
目录 1.系统的受众说明 2.系统可行性分析 2.1 经济可行性 2.2 技术可行性 2.2.1 Java Web技术 2.2.2 Eclipse 2.2.3 Tomcat 2.2.4 数据库 2.2.5 Layui框架 2.2.6 SSM框架 3.系统需求分析 3.1 用户需求分析 3.2 功能需求分析 3.3 其他需求分析 4.系统设计 4.1 系…...
flutter doctor 报错—CocoaPods not installed
执行命令 brew install cocoapodscommand not found: brew报错解决: 添加链接描述...
