最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园。
通过WPF的按钮、文本输入框实现了一个简单的SpinBox数字输入用户组件并可以通过数据绑定数值和步长。本文中介绍了通过Xaml代码实现自定义组件的布局,依赖属性的定义和使用等知识点。
完整代码见Github
SpinBox由一个文本输入框和两个箭头按钮组成,我们在Xaml
代码中先把基本的布局做好。其实可以发现自定义用户控件布局和普通的窗体布局的Xaml
代码差不多,只不过Xaml
的根标签从Window
变成了UserControl
。
<UserControl x:Class="SpinBox.MySpinBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SpinBox"
mc:Ignorable="d"
d:DesignHeight="36" d:DesignWidth="92">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="txtBoxValue" Grid.Column="0"
TextAlignment="Center" VerticalContentAlignment="Center"/>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="5*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" x:Name="btnPlus">▲</Button>
<Button Grid.Row="1" x:Name="btnMinor">▼</Button>
</Grid>
</Grid>
</UserControl>
因为我们是WPF中制作的用户组件,因此希望输入的数值、步长的配置等可以在Xaml
中实现。因此我们需要给我们新建的用户组件增加依赖属性。这里我们直接通过依赖属性值变化的回调函数来实现文本框信息的更新。
/// <summary>
/// SpinBox.xaml 的交互逻辑
/// </summary>
[ContentProperty("Value")]
public partial class MySpinBox : UserControl
{
/// <summary>
/// DepedencyProperty for Step
/// </summary>
public static readonly DependencyProperty StepProperty
= DependencyProperty.Register("Step", typeof(double),
typeof(MySpinBox), new PropertyMetadata(1.0));
/// <summary>
/// DepedencyProperty for Value
/// </summary>
public static readonly DependencyProperty ValueProperty
= DependencyProperty.Register("Value", typeof(double),
typeof(MySpinBox), new FrameworkPropertyMetadata(0.0,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault
| FrameworkPropertyMetadataOptions.Journal
| FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnValueChanged))
);
public double Value
{
get => (double)GetValue(ValueProperty);
set
{
if (Value != value)
{
SetValue(ValueProperty, value);
}
}
}
public double Step
{
get => (double)GetValue(StepProperty);
set
{
if (Step != value)
{
SetValue(StepProperty, value);
}
}
}
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var spinBox = d as MySpinBox;
if (spinBox != null)
{
spinBox.txtBoxValue.Text = e.NewValue.ToString();
}
}
}
接下来我们在MainWindow.xaml
中增加刚刚编写好的MySpinBox
组件
<Window x:Class="SpinBox.MainWindow"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SpinBox"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:MySpinBox MaxHeight="64" MaxWidth="128" Step="2" Value="5"/>
</Grid>
</Window>
我们在自定义组件中增加按钮组件的响应
<Button Grid.Row="0" x:Name="btnPlus" Click="btnPlus_Click">▲</Button>
<Button Grid.Row="1" x:Name="btnMinor" Click="btnMinor_Click">▼</Button>
在C#代码中增加对应的响应逻辑就能实现完整的效果
private void btnPlus_Click(object sender, RoutedEventArgs e)
{
Value += Step;
}
private void btnMinor_Click(object sender, RoutedEventArgs e)
{
Value -= Step;
}
最后需要说明下的是按钮的Unicode值得十六进制表示分别是0x25B2
和0x25BC
。Xaml
本质是一种XML
文本,因此在其中表示Unicode要使用XML
对应的语法格式。
通过WPF的按钮、文本输入框实现了一个简单的SpinBox数字输入用户组件并可以通过数据绑定数值和步长。本文中介绍了通过Xaml代码实现自定义组件的布局,依赖属性的定义和使用等知识点。
一个自定义WPF窗体的解决方案,借鉴了吕毅老师的WPF制作高性能的透明背景的异形窗口一文,并在此基础上增加了鼠标穿透的功能。可以使得透明窗体的鼠标事件穿透到下层,在下层窗体中响应。
实现了一个支持长短按得按钮组件,单击可以触发Click事件,长按可以触发LongPressed事件,长按松开时触发LongClick事件。还可以和自定义外观相结合,实现自定义的按钮外形。
WPF的按钮提供了Template模板,可以通过修改Template模板中的内容对按钮的样式进行自定义。结合资源字典,可以将自定义资源在xaml窗口、自定义控件或者整个App当中调用
早两天写了一篇S3简单上传文件的小工具,知乎上看到了一个问题问如何实现显示MINIO上传进度,因此拓展一下这个小工具能够在上传大文件时显示进度。