- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
在我们创建界面元素的时候,不管在Vue3+ElementPlus的前端上,还是Winform桌面端上,都是会利用自定义用户控件来快速重用一些自定义的界面内容,对自定义用户控件的封装处理,也是我们开发WPF应用需要熟悉的一环。本篇随笔继续深入介绍介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发,主要针对自定义用户控件的封装和使用做一些介绍.
在我们使用原生的WPF控件的时候,有时候发现常规的原生控件不够好看,或者功能达不到要求,就需要进行一定程度上的二次封装处理,也就是自定义控件的开发场景.
例如我们前面介绍到的用户信息的查询界面,我们没有找到一个输入数值范围的控件,如对于年龄等类似的属性,我们需要一个区间的查询处理,可以保留为空,或者最小、最大值之间进行查询,如下界面所示.
由于WPF没有这样的原生控件,我们需要的话,就需要使用常规的数值或者文本控件来进行处理,如果多次有这样的内容,封装为自定义控件,让她简单的使用,是最为优雅的方式.
我们看到控件的外观如下所示.
。
我们可以用Grid布局来进行处理,包括两个TextBlock和两个文本的控件界面,我们创建自定义控件后,在Xaml定义好布局信息.
< UserControl x:Class = " WHC.SugarProject.WpfUI.Controls.NumericRange " xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation " xmlns:x = " http://schemas.microsoft.com/winfx/2006/xaml " xmlns:d = " http://schemas.microsoft.com/expression/blend/2008 " xmlns:hc = " https://handyorg.github.io/handycontrol " xmlns:local = " clr-namespace:WHC.SugarProject.WpfUI.Controls " xmlns:mc = " http://schemas.openxmlformats.org/markup-compatibility/2006 " Name="NumericRangeControl" d:Background = " Transparent " d:DesignHeight = " 32 " d:DesignWidth = " 150 " d:Foreground = " White " mc:Ignorable = " d " > <Grid MinWidth= " 150 " > <Grid.ColumnDefinitions> <ColumnDefinition Width= " Auto " /> <ColumnDefinition Width= " * " /> <ColumnDefinition Width= " Auto " /> <ColumnDefinition Width= " * " /> </Grid.ColumnDefinitions> < TextBlock Grid.Column = " 0 " Margin = " 10,0,10,0 " VerticalAlignment = " Center " Text="{Binding Path=Text, RelativeSource={RelativeSource AncestorType={x:Type local:NumericRange}}}" /> < TextBox x:Name = " txtStart " Grid.Column = " 1 " Margin = " 5 " Text="{Binding Path=StartValue, Converter={StaticResource NumericConverter}, RelativeSource={RelativeSource AncestorType={x:Type local:NumericRange}}}" /> < TextBlock Grid.Column = " 2 " Margin = " 5,0,5,0 " VerticalAlignment = " Center " Text = " ~ " /> < TextBox x:Name = " txtEnd " Grid.Column = " 3 " Margin = " 5 " Text="{Binding Path=EndValue, Converter={StaticResource NumericConverter}, RelativeSource={RelativeSource AncestorType={x:Type local:NumericRange}}}" /> </Grid> </UserControl>
其中绑定动态属性的地方,我们使用下面代码 。
Text="{Binding Path=
StartValue
, Converter={StaticResource NumericConverter}, RelativeSource={RelativeSource AncestorType={x:Type local:NumericRange}}}"
当然也可以使用Element的标记方式,这种我们需要设置用户自定义控件名称为Name=“***”,如上面的代码设置为.
Name="
NumericRangeControl
"
这样我们就可以通过自定义控件的ElementName来定位绑定的属性了,等同于如下代码.
< TextBox x:Name ="txtStart" Grid.Column ="1" Margin ="5" Text =" {Binding Path=StartValue, Converter={StaticResource NumericConverter}, ElementName=NumericRangeControl } " />
前面我们介绍了该控件包含了的一些属性,如StartValue、EndValue、以及文本说明Text等,这些是在用户控件后台代码里面进行定义的自定义依赖属性的,我们来看看代码.
如我们增加一个StartValue,那么同时需要增加一个StartValueProperty的自定义依赖属性.
/// < summary > /// 开始值 /// </ summary > public decimal? StartValue { get { return (decimal?)GetValue(StartValueProperty); } set { SetValue(StartValueProperty, value); } } public static readonly DependencyProperty StartValueProperty = DependencyProperty.Register( nameof(StartValue), typeof(decimal?), typeof(NumericRange), new FrameworkPropertyMetadata(default(decimal?), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback( OnStartValuePropertyChanged )));
同时,这个属性的变化,会触发一个控件路由的事件OnStartValuePropertyChanged ,如下所示.
private static void OnStartValuePropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) { if (d is not NumericRange control) return ; if (control != null ) { var oldValue = ( decimal ?)e.OldValue; // 旧的值 var newValue = ( decimal ?)e.NewValue; // 更新的新的值 var args = new RoutedPropertyChangedEventArgs < decimal ?> (oldValue, newValue); args.RoutedEvent = NumericRange.ValueChangedEvent; control.RaiseEvent(args); control.ValueChangedCommand ?.Execute( null ); } }
除了触发路由事件外,我们可以给该控件定义一个Command 命令,类似按钮的命令处理,绑定后就可以接受到相关的通知了。Command的定义如下代码所示.
/// <summary> /// 数量改变命令 /// </summary> public static readonly DependencyProperty ValueChangedCommandProperty = DependencyProperty.Register( " ValueChangedCommand " , typeof (ICommand), typeof (NumericRange), new PropertyMetadata( default (ICommand))); /// <summary> /// 数量改变命令 /// </summary> public ICommand ValueChangedCommand { get { return (ICommand)GetValue(ValueChangedCommandProperty); } set { SetValue(ValueChangedCommandProperty, value); } }
自定义控件开发好后,使用也是很简单的,需要在页面或者窗口的定义部分,增加控件的命名空间,便于引用自定义控件,如下代码所示.
xmlns:Controls="clr-namespace:
WHC.SugarProject.WpfUI.Controls
"
这样我们在使用的时候,就和其他原生控件的使用差不多了。如下是在页面中使用的Xaml代码.
< Controls:NumericRange EndValue =" {Binding ViewModel.PageDto. AgeEnd , UpdateSourceTrigger=PropertyChanged} " StartValue =" {Binding ViewModel.PageDto. AgeStart , UpdateSourceTrigger=PropertyChanged} " Text ="年龄" ValueChangedCommand =" {Binding ViewModel. SearchCommand } " />
我们可以看到自定义控件的属性的绑定,和其他控件的属性绑定一致的,而且我们这里定义了一个Command: ValueChangedCommand 。
我们可以通过这个命令接收控件变化的通知。这样就可以正常的实现我们所需要的处理功能了.
另外,自定义控件的输入框,一般会在失去焦点后触发命令处理,我们也可以让文本输入框在输入后回车触发命令处理,我们增加一个KeyDown的事件处理,如下代码所示.
< TextBox x:Name ="txtStart" Grid.Column ="1" Margin ="5" KeyDown =" txtStartEndValue_KeyDown " Text =" {Binding Path=StartValue, Converter={StaticResource NumericConverter}, ElementName=NumericRangeControl} " /> < TextBlock Grid.Column ="2" Margin ="5,0,5,0" VerticalAlignment ="Center" Text ="~" /> < TextBox x:Name ="txtEnd" Grid.Column ="3" Margin ="5" KeyDown =" txtStartEndValue_KeyDown " Text =" {Binding Path=EndValue, Converter={StaticResource NumericConverter}, RelativeSource={RelativeSource AncestorType={x:Type local:NumericRange}}} " />
让回车切换到下一个焦点即可.
private void txtStartEndValue_KeyDown( object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { var textBox = sender as System.Windows.Controls.TextBox; if (textBox != null ) { // 切换焦点会触发值更新命令 textBox.MoveFocus( new TraversalRequest(FocusNavigationDirection.Next)); } } }
至此我们就完成了完美的控件处理事件了.
编译后,我们就可以在工具栏中看到用户自定义控件的列表了,可以直接拖动它到页面进行使用.
至此,我们就实现了自定义控件在页面上的使用了,非常简单.
。
当然,我们也可以组合一些面板,来实现更加复杂的控件呈现方式,可以设计一些图表、文本内容的综合展示,如下是其中的一个控件的多层展示.
根据不同的图标、内容,背景色、以及一些集合形状的叠加,就可以设计出非常好看的单个用户控件,然后动态设置,就可以很好的实现不同的内容展示.
。
最后此篇关于循序渐进介绍基于CommunityToolkit.Mvvm和HandyControl的WPF应用端开发(3)--自定义用户控件的文章就讲到这里了,如果你想了解更多关于循序渐进介绍基于CommunityToolkit.Mvvm和HandyControl的WPF应用端开发(3)--自定义用户控件的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
有没有办法在另一个 WPF 窗口内托管 WPF 窗口。我有几个有点复杂的表格。但现在为了简化事情,我试图将其中一些合并为一个“仪表板”表单中的标签页。 请注意,我不是要托管 Windows 窗体,而是
WPF 特有的哪些方面和实践在非 WPF GUI 编程中最有用(并且并非难以实现)? 最佳答案 通过学习 WPF 命令,我了解了命令模式。它构成了 UI - 代码分离的基础,我认为应该在其他应用程序中
WinRT/Metro 正在获得一个新的 SemanticZoom控制,但我很难为 WPF 找到任何东西。 我不想为我的特定项目切换到 Metro,因为它不允许我制作窗口应用程序或跨多个显示器的多个实
我很难解决我的问题,我快要疯了。 想法是这样的:我有两个 ListView 元素,当一个元素从第一个列表掉落到第二个列表时,我需要打开一个对话,但我需要被掉落的元素的信息以及被添加以填充对话的元素。
如果我遵循TabControl,并且一切正常,当我切换到第二个Tabitem时,它显示就没有问题。 //datagrid //datagrid2 但是如果我有这个xaml,当我
在 Windows 窗体应用程序中,我们的数据 GridView 有很多事件,如行鼠标双击或行单击以及额外的...... 但是在 WPF 中我找不到这些事件。我如何将行鼠标双击添加到其中包含数据网格的
在这个项目中,代码 正确编译和执行 ;但是,我需要帮助解决两个问题: VS2012 WPF 设计器不适用于此 XAML 文件。它显示消息设计 View 对于 x64 和 ARM 目标平台不可用。 我收
目前我正在设计 WPF ScrollViewer,我发现了这个 Content="M 0 0 L 4 4 L 0 8 Z" 阅读 MSDN examples .现在我真的很想知道这意味着什么,但我无法
在 WPF 中,元素的可见性可以为“可见”,但实际上在屏幕上不可见,因为它的父元素(或父元素的父元素)具有折叠的可见性。 我希望能够知道一个元素是否实际呈现在屏幕上,而不必遍历可视化树检查父元素。 有
我应该使用 ApplicationCommands.Close用于关闭模式对话框还是该命令被认为是为关闭应用程序保留的?如果是后者,请大家创建Close每个命令 Dialog盒子或只是一个 Close
WPF 是否有任何可用的 piemenu 控件? 最佳答案 我在我的最爱中找到了这个,你可以看看: This 祝你今天过得愉快。 关于wpf - WPF 的菜单,我们在Stack Overflow上找
我正在尝试使用 WrapPanel 和两个 TextBlock 将星号 (*) 附加到某些文本的左侧,允许文本换行,并强制文本右对齐。通过创建一个 FlowDirection 设置为 RightToL
这里是场景(简化):我在Window上有一个控件(比如说一个Rectangle)。我迷上了MouseMove事件,以使其启动拖放操作。然后在MouseDown事件中进行动画处理,向右移动50个像素。但
我有一个 ListView ,它的项目来源是一个列表。我希望用户只选择一项。当我将 listview 的 SelectionMode 设置为 single 时,用户仍然可以选择多个项目,并且似乎 li
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
INotifyPropertyChanged 的目的是什么。我知道每当更改属性时都会触发此事件,但是 View /用户界面如何知道触发了此事件: 这是实现 INotifyPropertyChang
我正在查看工具箱中的 WPF 组件,但找不到 2005/2008 中存在的错误提供程序。 被移除了吗? 最佳答案 ErrorProvider是一个 Winforms 控件。 WPF 中没有等效项。但是
我试图在单击和双击 wpf Image 控件时有不同的行为。不幸的是,单击首先被触发,因此双击被忽略。 最佳答案 如果您改用 MouseDown 事件,则它在 EventArgs 中为 ClickCo
这可能吗? 我使用了一个框架控件并且:显示(例如:showwindow.xaml) 但是我得到这个错误: root element is not valid for navigation 最佳答案 确
我在蓝色背景的窗口上放置了一个扩展器,我想让扩展器的按钮与默认颜色不同(蓝色,它是从窗口接收的)。当我修改扩展器的背景属性时,它会将整个扩展器、标题和全部更改为新颜色。但是,我只想更改按钮本身。谁能指
我是一名优秀的程序员,十分优秀!