一、前言

今天分享一下如何实现带递增递减按钮的TextBox控件

二、正文

1、之前的博客分享了一篇自定义XamlIcon控件的文章,这次就直接在那个项目的基础上实现今天这个自定义控件

2、首先添加两个图标资源,一个增加的按钮,一个减小的按钮,具体过程可以参考我之前写的文章

3、接着新增一个自定义控件,如图所示那个

4、添加后,项目中还会生成一个Themes文件夹,里面还有一个Generic.xaml的文件,这个文件可以用来写控件样式的,里面会自动生成一个最基础的控件样式,而那个NumberTextBox是用来后后台逻辑的

5、先来把控件的样式编写一下,如下,样式具体细节就不在描述,就是在里面添加了两个自定义的XamlIcon控件来作为递增和递减按钮,然后还添加了一个TextBlock来做提示文本

<Style TargetType="{x:Type ctls:NumberTextBox}">
<Setter Property="Cursor" Value="IBeam" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Foreground" Value="#555" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ctls:NumberTextBox}">
<Border
Name="Border"
Background="White"
BorderBrush="#AAA"
BorderThickness="1"
CornerRadius="3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<ScrollViewer
x:Name="PART_ContentHost"
Margin="6,0,0,0"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden" />
<TextBlock
x:Name="Hint"
Margin="6,0,0,0"
VerticalAlignment="{Binding ElementName=PART_ContentHost, Path=VerticalAlignment}"
Foreground="#c9ccd7"
Text="{TemplateBinding Tag}"
Visibility="Collapsed" />
<Border
Grid.Column="1"
Background="Transparent"
BorderBrush="#eee"
BorderThickness="1,0,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<ctls:XamlIcon
x:Name="InButton"
VerticalAlignment="Center"
Cursor="Hand"
Icon="angle_up" />
<Rectangle
Grid.Row="1"
Height="1"
Fill="#eee" />
<ctls:XamlIcon
x:Name="DeButton"
Grid.Row="2"
VerticalAlignment="Center"
Cursor="Hand"
Icon="angle_down" />
</Grid>
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Text" Value="{x:Null}">
<Setter TargetName="Hint" Property="Visibility" Value="{x:Static Visibility.Visible}" />
</Trigger>
<Trigger Property="Text" Value="">
<Setter TargetName="Hint" Property="Visibility" Value="{x:Static Visibility.Visible}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

6、接着就是编写后台部分代码,后台部分代码也比较简单,这里简单的添加了两个依赖属性,一个是递进值,一个是最小值。然后就是在OnApplyTemplate的重载中去给样式那里添加的两个控件添加鼠标点击事件。就先这样基础的实现先,复杂的功能后续在增加进去,比如限制只能输入数字之类的,今天主要先介绍实现的大致方法。

public class NumberTextBox : TextBox
{
public int Step
{
get { return (int)GetValue(StepProperty); }
set { SetValue(StepProperty, value); }
} public static readonly DependencyProperty StepProperty =
DependencyProperty.Register("Step", typeof(int), typeof(NumberTextBox), new PropertyMetadata(1)); public int Minimum
{
get { return (int)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(int), typeof(NumberTextBox), new PropertyMetadata(0)); static NumberTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumberTextBox), new FrameworkPropertyMetadata(typeof(NumberTextBox)));
} public NumberTextBox()
{
InputMethod.SetIsInputMethodEnabled(this, false);
} public override void OnApplyTemplate()
{
base.OnApplyTemplate();
XamlIcon DeButton = (XamlIcon)this.Template.FindName("DeButton", this);
XamlIcon InButton = (XamlIcon)this.Template.FindName("InButton", this); DeButton.MouseLeftButtonDown += DeButton_MouseLeftButtonDown;
InButton.MouseLeftButtonDown += InButton_MouseLeftButtonDown;
} private void DeButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (!String.IsNullOrEmpty(this.Text))
{
this.Text = int.Parse(this.Text) - Step < Minimum ? Minimum + "" : int.Parse(this.Text) - Step + "";
this.SelectionStart = this.Text.Length;
}
else
{
this.Text = Minimum + "";
this.SelectionStart = this.Text.Length;
}
} private void InButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (!String.IsNullOrEmpty(this.Text))
{
this.Text = int.Parse(this.Text) + Step + "";
this.SelectionStart = this.Text.Length;
}
else
{
this.Text = Minimum + "";
this.SelectionStart = this.Text.Length;
}
}
}

7、测试控件功能,主界面添加自定义好的控件,如下

<Window x:Class="XamlIconDemo.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:ctls="clr-namespace:XamlIconDemo.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:XamlIconDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ctls:NumberTextBox
Width="200"
Height="40"
FontSize="22"
Minimum="0"
Step="5"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Tag="请输入数字..."/>
</Grid>
</Window>

8、实现效果如下,基础功能已经算实现了,但还不完善,有需要的可以自己完善完善,今天的分享就到这了

WPF开发随笔收录-带递增递减按钮TextBox的更多相关文章

  1. WPF开发随笔收录-仿安卓Toast

    一.前言 在项目中,经常需要用到消息提醒功能,在以前接触安卓开发那会使用过Toast,于是打算在WPF上也来模仿一个,话不多说,撸起袖子干起来! 二.正文 1.首先新建一个工程,工程的目录如下 2.编 ...

  2. WPF开发随笔收录-ScrollViewer滑块太小解决方案

    一.前言 在WPF开发过程中,ScrollViewer是一个很常使用到的控件,在自己工作的项目中,收到一个反馈就是当ScrollViewer里面的内容太长时,滚动条的滑块就会变得很小,然后导致点击起来 ...

  3. WPF开发随笔收录-DrawingVisual绘制高性能曲线图

    一.前言 项目中涉及到了心率监测,而且数据量达到了百万级别,通过WPF实现大数据曲线图时,尝试过最基础的Canvas来实现,但是性能堪忧,而且全部画出来也不实际.同时也尝试过找第三方的开源库,但是因为 ...

  4. WPF开发随笔收录-唯一标识符GUID

    一.前言 该系列博客用于记录本人在WPF开发过程中遇到的各种知识点 二.正文 1.在工作的项目中,软件需要用到在线升级功能,由于第一次弄,在下载服务端的文件到本地时,文件的名称我选择直接生成为固定的格 ...

  5. WPF开发随笔收录-心电图曲线绘制

    一.前言 项目中之前涉及到胎儿心率图曲线的绘制,最近项目中还需要添加心电曲线和血样曲线的绘制功能.今天就来分享一下心电曲线的绘制方式: 二.正文 1.胎儿心率曲线的绘制是通过DrawingVisual ...

  6. WPF开发随笔收录-获取软件当前目录的坑

    一.唠唠叨叨 软件开发过程中,经常需要使用到获取exe当前目录这个功能,前同事在实现这个需求时使用的是Directory.GetCurrentDirectory()这个方法,但再最近的测试中,突然发现 ...

  7. WPF开发随笔收录-DataAnnotations实现数据校验(MVVM架构下)

    一.前言 在自己的项目中挺多地方需要涉及到数据验证的,初期的实现方式都是通过点击确定后再逐个验证数据是否符合要求,但这种方式会让后台代码变得很多很乱.于是就开始在网上需求好的解决方式,刚好看到了一个大 ...

  8. WPF开发随笔收录-报警闪烁效果实现

    一.前言 工作中目前经手的项目是医疗相关的监护软件,所以会涉及到一些报警效果的实现,今天在这里就简单分享一下实现方式 二.正文 1.实现的方式比较的简单,就是通过一个Border控件,然后搭配Data ...

  9. WPF开发随笔收录-本地日志LogUtil类

    一.前言 生活中的日志是记录你生活的点点滴滴,让它把你内心的世界表露出来,更好的诠释自己的内心世界.而在开发者眼中的日志是我们排除问题的第一手资料,项目中的程序上线之后,一旦发生异常,第一件事就是先去 ...

随机推荐

  1. OSPF 路由协议详解(一)

    (文章目录) ospf 协议是网络层协议 此篇文章适合有一定网络基础的人 ospf 协议最多应用在企业网络中,针对于运营商网络并不是特别的适用,端口号为 89 通过 IP 进行数据的转发 ospf 基 ...

  2. Vue使用PostCSS 插件和如何使用sass及常用语法

    为什么要使用PostCss 转换 px 单位的插件有很多,知名的有 postcss-px-to-viewport 和 postcss-pxtorem,前者是将 px 转成 vw,后者是将 px 转成 ...

  3. go sync.map源码解析

    go中的map是并发不安全的,同时多个协程读取不会出现问题,但是多个协程 同时读写就会出现 fatal error:concurrent map read and map write的错误.通用的解决 ...

  4. TemplatesImpl利用链

    FastJson利用链 Fastjson的版本在1.2.22-1.2.24主要有两条链利用TemplatsImpl和JdbcRowSetImpl利用链先来学习TemplatsImpl利用链,这个与前面 ...

  5. InnoDB的逻辑存储结构是什么,表空间组成包括哪些?

    一.表空间 在InnoDB中我们创建的表还有对应的索引数据都存储在扩展名为.ibd 的文件中,这个文件路径可以先通过查mysql变量datadir来得到,然后进入对应的数据库名目录,会看到很多ibd, ...

  6. 『现学现忘』Git基础 — 22、Git中文件重命名

    目录 1.用学过的命令进行文件重命名 2.使用git mv命令进行文件重命名 我们这篇文章来说说在Git中如何进行文件重命名. 提示一下,下面所说明的是对已经被Git管理的文件进行重命名,未被Git追 ...

  7. zabbix 添加监控交换机温度item

    首先需要获取到交换机温度对应的OID,可以官方文档进行查询(多为私有OID),以盛科为例 官方文档查询到温度节点对于的OID为 10.0.3.102 1.3.6.1.4.1.27975.37.1.3. ...

  8. mybatis 查询返回的类型中字段类型为 List<xx>

    基本类型数组 mapper.xml <resultMap id="xxDtoResultMap" type="com.xx.xxDto"> < ...

  9. Redis设计与实现3.3:集群

    集群 这是<Redis设计与实现>系列的文章,系列导航:Redis设计与实现笔记 集群中的节点 创建集群 通过 CLUSTER NODE 命令可以查看当前集群中的节点.刚启动时,默认每一台 ...

  10. 用更云原生的方式做诊断|大规模 K8s 集群诊断利器深度解析

    背景 通常而言,集群的稳定性决定了一个平台的服务质量以及对外口碑,当一个平台管理了相当规模数量的 Kubernetes 集群之后,在稳定性这件事上也许会"稍显被动". 我们可能经常 ...