用系统滚动条实现NumericUpDown的原理

我们知道在Windows控件里有一个叫NumericUpDown的控件,使用这个控件后可以用鼠标点击或键盘上下键来微调数字,当然也可以直接输入。这是一个使用方便同时又能限制输入格式的很有用的控件,可惜在Web中却没有提供这个控件,我们只能面对几个土土的INPUT的衍生控件。

    不过也有很多人制作了NumericUpDown这个控件替代品,但是由于Web上同样没有提供ScrollBar这个控件,那些替代品一个通病就是模拟的用来微调那两个button始终不太和谐,而且显示的效果受网页字体的影响很大。最常用的就是用图片了,那样字体一大就完全对不上了,不是看图片不完整,就是看半个数字,真的是很恼火。

    有没有办法借用系统的滚动条来实现NumericUpDown控件中的微调button呢?这个确实比较的难,我们最容易想到的就是使用INPUT type="text"和Select把它们弄成一行高,然后就会出现和Windows的NumericUpDown控件十分相像的微调button。那正好啊,可是问题是这两个控件的滚动条的出现是一个系统的行为,而不是HTML元素的行为(不是指的behavior哦),我们没有办法去读取和设置这滚动条的属性,就象使用Select,我们甚至都做出了外观很professional的NUD控件了,可是却完全没有办法使用脚本读取和设置我们想要的数值 emsad.gif

    既然不能响应系统滚动条的任何事件,那么我们就该从别的地方想办法了。使用viewport窗口里的onScroll事件来触发执行,因为只要滚动条有移动,onScroll就会触发,等于间接的俘获了系统滚动条上的点击事件,又因为可以通过onScroll的增量的正负来确定是Up按钮被点击了,还是Down按钮被点击了。那么使用这个特性来实现NumericUpDown控件似乎理所当然了?可是不幸还是有一些问题。

    假如我们使用div元素来做一个NumericUpDown控件,
0 11 1
。这个按钮已经很professinal了,而且不会受字体大小的任何影响。那么问题是什么呢?问题是当我们使用鼠标点击时按钮后,onScroll事件会被触发n(1-4)次@_@。当然使用鼠标滚轮或键盘上下键,也会触发n次onScroll事件。这个n到底可不可以度量呢?幸好是可以的,原来它是受字体大小影响的,当字体时Smallest时,n=1;字体时Smaller时,n=2;字体时Medium、Larger和Largest时,n=3或4。

    那么就算我们要使用onScroll也不能这么去判断n值呀,而且3或4的取值还不一定呢。后来又发现这些onScroll触发时的时间都是一样的,至少使用getTime()获得的毫秒值是相同的。用这个timestamp来判断也有还有问题,怎么都是问题啊,嗯,还真的都是问题。就是怎么去计数这几个timestamp相同的onScroll的问题。这个问题解决了,那么Web上的NumericUpDown控件就将会非常的professinal了emsmile.gif


本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 WPF 中的自定义控件来实现类似 WinForm 中的 NumericUpDown 控件。下面是一个简单的实现: 首先,创建一个新的 UserControl,命名为 NumericUpDown。在 UserControl 中添加两个 Button 控件,一个 TextBox 控件和一个 Label 控件,如下所示: ```xml <UserControl x:Class="WpfApp1.NumericUpDown" 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" mc:Ignorable="d" d:DesignHeight="30" d:DesignWidth="120"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBox x:Name="TextBox" Grid.Column="0" /> <Grid Grid.Column="1"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Button x:Name="UpButton" Grid.Row="0" Content="▲" Click="UpButton_Click" /> <Button x:Name="DownButton" Grid.Row="1" Content="▼" Click="DownButton_Click" /> </Grid> <Label x:Name="Label" Content="Label" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,-20,0,0" /> </Grid> </UserControl> ``` 然后,在 NumericUpDown.xaml.cs 文件中添加以下代码: ```csharp public partial class NumericUpDown : UserControl { public NumericUpDown() { InitializeComponent(); } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ValueChangedCallback)); public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(double.MinValue)); public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(double.MaxValue)); public double Value { get { return (double)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } public double Minimum { get { return (double)GetValue(MinimumProperty); } set { SetValue(MinimumProperty, value); } } public double Maximum { get { return (double)GetValue(MaximumProperty); } set { SetValue(MaximumProperty, value); } } private static void ValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { var numericUpDown = d as NumericUpDown; if (numericUpDown != null) { numericUpDown.TextBox.Text = e.NewValue.ToString(); } } private void UpButton_Click(object sender, RoutedEventArgs e) { var newValue = Value + 1.0; if (newValue <= Maximum) { Value = newValue; } } private void DownButton_Click(object sender, RoutedEventArgs e) { var newValue = Value - 1.0; if (newValue >= Minimum) { Value = newValue; } } } ``` 这里我们创建了 Value、Minimum 和 Maximum 三个依赖属性,分别表示当前值、最小值和最大值。当 Value 属性改变时,我们将文本框中的值更新为新值。当 UpButton 或 DownButton 被单击时,我们检查新值是否在最小值和最大值之间。如果是,则更新 Value 属性。最后,可以在 MainWindow.xaml 中使用 NumericUpDown 控件: ```xml <StackPanel> <Label>Value:</Label> <local:NumericUpDown Value="0" Minimum="-10" Maximum="10" /> </StackPanel> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值