带清空按钮TextBox的实现(WPF)
博文内容:通过Style制定包含清空Button的TextBox样式模板,通过在Style中引入自定义类的附加属性完成对TextBox的内容清空。
- <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">博文目的:帮助刚入门的WPF开发人员或有需要的人快速了解该样式的实现。由于本人水平有限,难免有不足的地方,欢迎请指正,共同进步!</span>
正题:
带清空按钮TextBox的实现(WPF)分为两部分:样式模板(Style)部分和附加属性类(TextBoxHelper)部分。
一、样式模板(Style)
我们先定义Style,目标类型:TextBox
下面针对TextBox的Template部分详细说明:
关键代码如下(只保留核心属性设置)
- <ControlTemplate TargetType="{x:Type TextBox}">
- <Border >
- <DockPanel LastChildFill="True">
- <Button x:Name="Part_ClearButton" DockPanel.Dock="Right" Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}" />
- <ScrollViewer x:Name="PART_ContentHost" DockPanel.Dock="Left" />
- </DockPanel>
- </Border>
- <ControlTemplate.Triggers>
- <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
- <Setter TargetName="Part_ClearButton" Property="Visibility" Value="Collapsed" />
- </DataTrigger>
- ................................省略
- </ControlTemplate.Triggers>
- </ControlTemplate>
为了方便直观理解,下图为样式模板(ControlTemplate)的示意图。
关于ControlTemplate相信大家都有个大概了解了,下面针对其中容易出错的地方补充几点说明:
1.关于最外层的Border对于它的 BorderBrush、BorderThickness、 SnapsToDevicePixels、 Background最好都不要自己设定尽量都使用TemplateBinding绑定到应用模板的TextBox上。原因嘛,当然是为了留给用户使用时尽量多的对于TextBox外观自主权,总不能说用了这个Style后边框、背景都不能设定吧。
2.对于DockPanel,其属性LastChildFill="True",本身默认值即为“True”,可以省略不写,但是一定要知道。
3.关于DockPanel中ScrollViewer和Button的布局,一定要先定义Button,后定义ScrollViewer。原因:就是因为第2条的LastChildFill="True"属性,如果先定义ScrollViewer,后定义Button会出现什么效果,大家可以自己试试看。
4.对于ScrollViewer 它的名字一定要是"PART_ContentHost" 否则将Windows将无法识别导致不能显示文字。
5.对于Button为了是Button显示正方形所以Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}" 将自己的宽绑定到了实际显示高度上。最好将Focusable设为False。原因:防止输入时点击清空按钮导致ScrollViewer失去焦点,具体表现为点击清空按钮,输入框的光标不闪烁了。FontSize尽量TemplateBinding到应用模板的目标控件上。
将Style重构提取,最后放入资源词典以供重用。
提炼后的Style
- <!--获得焦点后边框颜色-->
- <SolidColorBrush x:Key="FocusedBorderBrush" Color="Black"/>
- <!--鼠标移上时背景色-->
- <SolidColorBrush x:Key="MouseOverBackground" Color="LightGray"/>
- <!--清空按钮模板样式-->
- <ControlTemplate x:Key="ClearButtonTemplate" TargetType="Button">
- <Grid>
- <Rectangle x:Name="rctButton" Fill="Transparent" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Rectangle>
- <ContentPresenter Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"
- HorizontalAlignment="Center"
- VerticalAlignment="Center">
- </ContentPresenter>
- </Grid>
- <ControlTemplate.Triggers>
- <Trigger Property="IsMouseOver" Value="True">
- <Setter TargetName="rctButton" Property="Fill" Value="{DynamicResource MouseOverBackground}"/>
- </Trigger>
- </ControlTemplate.Triggers>
- </ControlTemplate>
- <!--带有清空按钮的TextBox风格-->
- <Style x:Key="ClearButtonTextBoxStyle" TargetType="{x:Type TextBox}">
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type TextBox}">
- <Border x:Name="bdRoot"
- BorderBrush="{TemplateBinding BorderBrush}"
- BorderThickness="{TemplateBinding BorderThickness}"
- SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
- Background="{TemplateBinding Background}">
- <DockPanel LastChildFill="True">
- <Button x:Name="Part_ClearButton"
- UC:TextBoxHelper.IsClearButton="True"
- Content="X"
- DockPanel.Dock="Right"
- Focusable="False"
- Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}"
- Template="{DynamicResource ClearButtonTemplate}"
- FontSize="{TemplateBinding FontSize}">
- </Button>
- <ScrollViewer x:Name="PART_ContentHost" DockPanel.Dock="Left" Background="{TemplateBinding Background}"/>
- </DockPanel>
- </Border>
- <ControlTemplate.Triggers>
- <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
- <Setter TargetName="Part_ClearButton" Property="Visibility" Value="Collapsed" />
- </DataTrigger>
- <Trigger Property="IsFocused" Value="True">
- <Setter TargetName="bdRoot" Property="BorderBrush" Value="{DynamicResource FocusedBorderBrush}"/>
- </Trigger>
- <Trigger Property="IsMouseOver" Value="True">
- <Setter TargetName="bdRoot" Property="BorderBrush" Value="{DynamicResource FocusedBorderBrush}"/>
- </Trigger>
- </ControlTemplate.Triggers>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
二、附加属性类
为什么不采用Trigger置空Text实现而要采用附加属性类?
以下为原因,不关心的可以跳过...
- <DataTrigger Binding="{Binding IsPressed,ElementName=Part_ClearButton}" Value="True">
- <Setter Property="Text" Value=""/>
- </DataTrigger>
当清空按钮按下时,触发
- <Setter Property="Text" Value=""/>
- <TextBox Text="{Binding xxx}"
- Visibility="Collapsed"
- Height="24"
- Width="250"
- Style="{DynamicResource ClearButtonTextBoxStyle}"
- >
- </TextBox>
或
- <TextBox Text="xxx"
- Visibility="Collapsed"
- Height="24"
- Width="250"
- Style="{DynamicResource ClearButtonTextBoxStyle}"
- >
- </TextBox>
此时,风格中 的触发器将失效,无法清空文本内容,经尝试,Trigger、DataTrigger均会失效,而且"Text"属性不支持StoryBorad也无法通过故事板清空。
使用附加属性清空文本内容
原理,通过在Style的ControlTemplate中 的清空按钮Part_ClearButton
加上自定义的附加属性,在附加属性改变的回调函数中获得依赖对象,该对象即为我们定义的Part_ClearButton
,获得按钮后为它的Click挂上我们的自定义事件,这样当点击清空按钮时,即可执行我们的自定义事件,只需要在事件里通过VisualTreeHelper.GetParent向上获取到应用模板的TextBox,然后通过TextBox.Clear()清空内容即可.
- public class TextBoxHelper
- {
- #region 附加属性 IsClearButton
- /// <summary>
- /// 附加属性,是否带清空按钮
- /// </summary>
- public static readonly DependencyProperty IsClearButtonProperty =
- DependencyProperty.RegisterAttached("IsClearButton", typeof(bool), typeof(TextBoxHelper), new PropertyMetadata(false, ClearText));
- public static bool GetIsClearButton(DependencyObject obj)
- {
- return (bool)obj.GetValue(IsClearButtonProperty);
- }
- public static void SetIsClearButton(DependencyObject obj, bool value)
- {
- obj.SetValue(IsClearButtonProperty, value);
- }
- #endregion
- #region 回调函数和清空输入框内容的实现
- /// <summary>
- /// 回调函数若附加属性IsClearButton值为True则挂载清空TextBox内容的函数
- /// </summary>
- /// <param name="d">属性所属依赖对象</param>
- /// <param name="e">属性改变事件参数</param>
- private static void ClearText(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- Button btn = d as Button;
- if (d != null && e.OldValue != e.NewValue)
- {
- btn.Click -= ClearTextClicked;
- if ((bool)e.NewValue)
- {
- btn.Click += ClearTextClicked;
- }
- }
- }
- /// <summary>
- /// 清空应用该附加属性的父TextBox内容函数
- /// </summary>
- /// <param name="sender">发送对象</param>
- /// <param name="e">路由事件参数</param>
- public static void ClearTextClicked(object sender, RoutedEventArgs e)
- {
- Button btn = sender as Button;
- if (btn != null)
- {
- var parent = VisualTreeHelper.GetParent(btn);
- while (!(parent is TextBox))
- {
- parent = VisualTreeHelper.GetParent(parent);
- }
- TextBox txt = parent as TextBox;
- if (txt != null)
- {
- txt.Clear();
- }
- }
- }
- #endregion
- }
最后我们在Style所在地引入TextBoxHelper命名空间,在Style的ControlTemplate里的按钮加上改附加属性即可
- <Button x:Name="Part_ClearButton"
- UC:TextBoxHelper.IsClearButton="True"
- Content="X"
- DockPanel.Dock="Right"
- Focusable="False"
- Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}"
- Template="{DynamicResource ClearButtonTemplate}"
- FontSize="{TemplateBinding FontSize}">
- </Button>
总结
经过以上博文,相信大家都理解带清空按钮TextBox的实现,当然这只是一个开始!最后把源代码上传,分享给大家,有什么不足的地方欢迎指正,谢谢!
带清空按钮TextBox的实现(WPF)的更多相关文章
- android自定义文本框,后面带清空按钮
android常见的带清空按钮的文本框,获得焦点时如果有内容则显示,否则不显示 package com.qc.health.weight; import com.qc.health.R; import ...
- 带清空按钮的EditText
public class ClearEditText extends EditText implements OnFocusChangeListener, TextWatcher { // 删除按钮的 ...
- WPF 带清除按钮的文字框SearchTextBox
原文:WPF 带清除按钮的文字框SearchTextBox 基于TextBox的带清除按钮的搜索框 样式部分: <!--带清除按钮文字框--> <Style TargetType=& ...
- WPF 实现带标题的TextBox
这篇博客将分享在WPF中如何创建一个带Title的TextBox.首先请看一下最终的效果, 实现思路:使用TextBlock+TextBox来实现,TextBlock用来显示Title. 实现代码, ...
- easyui datebox 扩展清空按钮及日期判断
<input id="EndHavDate" class="easyui-datebox" data-options="prompt:'请选择结 ...
- [iOS-UI]点击清空按钮,却会有提交的感觉
一,问题分析 1.感觉像是点击清空按钮时调用了添加按钮的事件. 2.插入断电后,还真是这样. 3.仔细想想,才发现,原来是我复制了添加按钮,变成为添加按钮,进而点击清空时,不仅清空了所有内容,还把最新 ...
- jquery图片滚动仿QQ商城带左右按钮控制焦点图片切换滚动
jquery图片滚动仿QQ商城带左右按钮控制焦点图片切换滚动 http://www.17sucai.com/pins/demoshow/382
- EasyUI 1.3.6 DateBox添加清空按钮
EasyUI 1.3.6 DateBox添加清空按钮 效果如图: EasyUI datebox是没有清空按钮的,可通过如下方法加入: 打开jquery.easyui.min.js看到这样如此乱的代码, ...
- 为jEasyUi的日期控件添加一个“清空”按钮----通过修改1.4的easyui.min.js
为 jQuery EasyUI 1.4 的datebox或datetimebox添加一个清空按钮 使用场景:为用户指定了日期的格式,且日期可以为空 修改语言包easyui-lang-zh_CN.js ...
随机推荐
- MySQL中的锁、隔离等级和读场景
一.导言 关于MySQL中的锁还有隔离等级这类话题,其概念性的解释早已泛滥.记住其概念,算不上什么.更重要的是思考:他们的区别和联系在哪儿,为什么会有这样的概念. 1)MySQL的锁(Lock)分为行 ...
- 调试Felix Framework
这里是指用Eclipse调试Felix Framework自身. 1. 首先安装Eclipse Java EE,然后再安装Java Source Attacher,这样才会在Jar文件的右键菜单“属性 ...
- OFBiz:组件装入位置
默认的,OFBiz会在framework.applications.specialpurpose.hot-deploy这几个目录寻找组件,在themes目录中寻找主题.OFBiz是通过framewor ...
- 转载【微信支付】jsapi支付之传参问题(使用微信官方SDK之PHP版本) V3之WxpayPubHelper 亲测有效,V3WxpayAPI_php_v3.zip版未测试,理论上也是一样的。
本文转载至:http://blog.csdn.net/geeklx/article/details/51146151 (微信支付现在分为v2版和v3版,2014年9月10号之前申请的为v2版,之后申请 ...
- brew install memcache get Error: Formulae found in multiple taps
本篇文章由:http://xinpure.com/brew-install-memcache-get-error-formulae-found-in-multiple-taps/ 安装环境: Mac ...
- 【web开发学习笔记】Struts-Tags学习笔记1 - 通用标签和控制标签
通用标签和控制标签 第一部分.代码 //前端 <html> <head> <meta http-equiv="Content-Type" conten ...
- JAX-WS HandlerChain使用具体解释
JAX-WS的Handler和Servlet的Filter相似,能够对全部WebServicer进行拦截,在Handler中能够记录日志.权限控制.对请求的SOAP消息进行加密.解密等.JAX-WS提 ...
- Object-C中的类-类的声明
1.关键字命名:为了避免与已有的c,C++关键字冲突,ObjectC关键字都有@开始: 如:@classs,@interface,@private,@try,@catch,@protocol等. 2 ...
- Android 使用PLDroidPlayer播放网络视频 依据视频角度自己主动旋转
近期由于项目需求 .须要播放网络视频 .于是乎 研究了一番 ,说说我遇到的那些坑 如今市面上有几个比較主流好用的第三方框架 Vitamio ( 体积比較大,有商业化风险 github:https:// ...
- springmvc mybatis 声明式事务管理回滚失效,(checked回滚)捕捉异常,传输错误信息
一.知识点及问题 后端框架: Spring .Spring mvc .mybatis 业务需求: client先从服务端获取用户大量信息到client,编辑完毕之后统一Post至服务端,对于数据的改动 ...