WPF中下拉框即可以选择项也可以作为只读文本框使用
1、需求
当前在开发的系统需要一个这样的控件。
(1)可以选择已有的选择项,类似于ComboBox选择;
(2)可以通过其他按钮点击,选择一个文件,选择后,把文件路径显示到控件上,并且处于只读状态,行为和只读状态下的TextBox保持一致。
更直观些,就是实现类似ArcMap中Toolbox中的数据集选择下拉框,如下图所示。

该控件可以通过下拉的方式,选择左侧的图层数据,又可以通过点击右侧的打开文件按钮,弹出打开文件对话框,选择要设置的数据文件。该控件还可以通过键盘输入,但我们的需求是禁止输入,只能选择和通过打开文件对话框设置。
2、现有的ComboBox
我计划在WPF中的ComboBox控件的基础上进行开发,首先看通过简单的属性设置是否能够满足要求。
(1)不设置任何参数
在不设置任何参数的情况下,效果如下图所示。

可以显示底图上加载的数据,但点击【Select】按钮,通过设置ComboBox.Text属性,数据显示不出来,这种效果离我们想要的还差十万八千里。
(2)设置ComboBox.IsEditable=true
下面我们尝试通过设置ComboBox的实行看能不能达到我们想要的效果。首先把ComboBox.IsEditable属性设置为true,然后测试下Text属性设置后是否有效果了。

目前可以把选择的文件路径设置到ComboBox.Text了,并且可以正常显示,但鼠标点上去,文本框的内容可以修改,这不是我们想要的。于是发现ComboBox有个IsReadOnly属性,把该属性设置为true尝试一下试试。

目前下拉框中的内容不能修改了,但实际操作的时候会发现有些别扭。当鼠标点击下拉框,激活该控件的时候,里面的文字默认处于全选状态,此时想拖动鼠标,把文字拖动到尾部是操作不了的,只能再次点击下拉框中的内容,才可以和普通文本框的操作一样通过鼠标拖动视图。
经过各种尝试,发现当ComboBox控件GotFocus的时候,里面的文字会默认处于全选状态,这个我们需要解决一下。
3、使用VisualTreeHelper单独处理TextBox
在网上查询,发现ComboBox在IsEditable=true的状态下,是有很多个控件组合而成的。如下图所示。

我们可以调用VisualTreeHelper,获取这个TextBox,不过需要在Load后,再调用,不然这些控件是获取不到的。
this.Loaded += (x, y) =>
{
var myMainGrid = VisualTreeHelper.GetChild(this, 0);
var myTextBox = VisualTreeHelper.GetChild(myMainGrid, 4) as TextBox;
myTextBox.IsReadOnly = true;
myTextBox.IsReadOnlyCaretVisible = true;
};
获取TextBox后,我们需要解决ComboBox激活后,文字全选的问题。代码如下。
myTextBox.GotFocus += (m, n) =>
{
myTextBox.SelectionOpacity = 0;
this._IsNeedClearSelection = true;
};
该代码的的作用是当TextBox得到焦点后,立刻把TextBox中文字选中的背景颜色的透明度设置为0,这样使用着就感觉不出来文字被选中了。
鼠标左键弹起前,需要清空选中文字,并把光标放到鼠标点击处,并还原文本选中的颜色,代码如下。
myTextBox.PreviewMouseLeftButtonUp += (m, n) =>
{
if (this._IsNeedClearSelection == false)
{
return;
}
var myPosition = n.GetPosition(myTextBox);
int mySelectionStart = myTextBox.GetCharacterIndexFromPoint(myPosition, true);
myTextBox.Select(mySelectionStart, 0);
this._IsNeedClearSelection = false;
myTextBox.SelectionOpacity = 0.4;
};
此时,基本上ComboBox能够满足我们的需求了,效果如下图所示。

但还有一个问题,就是在ComboBox在IsEditable=true的状态下,鼠标移动到可选项上的时候,选择项不高亮了。为了解决这个问题,尝试了很多方法,都不行,准备放弃,就这样了。
因为系统使用了DEV for WPF UI库,忽然想到了WPF DEV中的ComboBoxEdit,之前测试过,通过设置属性,满足不了需求。但没有使用VisualTreeHelper,深入的去测试,那就再尝试下试试。
4、使用WPF DEV中的ComboBoxEdit
测试的时候,ComboBoxEdit在任何属性都不设置的情况下,除了文字可以编辑,其他的都可以满足要求。于是我们设置IsReadOnly=True,但这个时候,下拉框中的可选择项都处于不可用状态,也不能选择,所以IsReadOnly属性不能设置成True。尝试了一下有可能性的其他属性,例如EditMode等,都不能满足需求。
但在测试ComboBox的时候,知道了WPF的可视化树这个概念,可以通过VisualTreeHelper获取组成控件的子控件。于是加载后,在Load事件中,我们查看下ComboBoxEdit组织树,如下图所示。

我们看到了里面有个TextBox控件,这个就是显示文本的控件了,感觉是不是获取到这个TextBox然后把该TextBox设置成只读是不是问题就完美解决了?
这个树比较深,我们就找了一段根据类型获取元素的代码,如下图所示。
public static List<T> FindVisualChild<T>(DependencyObject pDependencyObject) where T : DependencyObject
{
List<T> myTList = new List<T> { };
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(pDependencyObject); i++)
{
DependencyObject myChild = VisualTreeHelper.GetChild(pDependencyObject, i);
if (myChild != null && myChild is T myT)
{
myTList.Add(myT);
List<T> myChildOfChildren = FindVisualChild<T>(myChild);
if (myChildOfChildren != null)
{
myTList.AddRange(myChildOfChildren);
}
}
else
{
List<T> myChildOfChildren = FindVisualChild<T>(myChild);
if (myChildOfChildren != null)
{
myTList.AddRange(myChildOfChildren);
}
}
}
return myTList;
}
获取TextBox和设置其属性的代码如下。
public class DatasetComboBoxExUI : ComboBoxEdit
{
public DatasetComboBoxExUI()
{
this.Loaded += (x, y) =>
{
List<TextBox> myTextBoxList = VisualTreeExHelper.FindVisualChild<TextBox>(this);
if (myTextBoxList.Count == 0)
{
return;
}
var myTextBox = myTextBoxList[0];
myTextBox.IsReadOnly = true;
myTextBox.IsReadOnlyCaretVisible = true;
};
}
}
启动测试,效果非常完美,正是我们需要的,界面如下图所示。

5、总结
最开始测试Dev中的ComboBoxEdit,通过设置属性各种尝试,发现满足不了需求。既然ComboBoxEdit满足不了需求,那就在WPF原生态的ComboBox上测试吧。
开始也是设置ComboBox的属性,各种测试后,发现还是不行。在网上搜索的时候,发现可以通过VisualTreeHelper获取组成ComboBox的UI树,从而对其内部的控件进行操作。VisualTreeHelper之前也用过,但在这块确实没往这块想。
通过VisualTreeHelper获取ComboBox中的TextBox,通过各种尝试,终于达到了一个比较满意的效果,此时已经花了一下午的时间。晚上下班回家后,想把这个过程整理一下,使用的时候,ComboBox在IsEditable=true的状态下,鼠标移动到可选项上的时候,选择项不高亮了。于是想把这个问题再解决下,以达到最完美效果。
但花了两个小时左右,一点思路也没有,在网上也没找到相关的资料。此时忽然想到,此前测试Dev中的ComboBoxEdit时候,还没想到过VisualTreeHelper这个方法,所以还没测试,那就测试下试试。
于是修改了代码,查看了下ComboBoxEdit的可视化树,发现里面有个TextBox,此时感觉希望非常大,因为当时放弃ComboBoxEdit是因为显示的内容可编辑,又不能设置ComboBoxEdit的IsReadOnly属性为True。现在看到ComboBoxEdit里面有个TextBox,如果我们获取TextBox,把这个TextBox的IsReadOnly属性为True不就可以了?
于是按照这个思路尝试了一下,最后效果非常完美,完全满足系统需求。
WPF中下拉框即可以选择项也可以作为只读文本框使用的更多相关文章
- jquery选中将select下拉框中一项后赋值给text文本框
jquery选中将select下拉框中一项后赋值给text文本框,出现无法将第一个下拉框的value赋值给文本框 因为select默认选中第一项..在选择第一项时,便导致无法激发onchange事件. ...
- DevExpress GridControl 中下拉框联动效果的实现(及支持文本框录入情况)
先解释一下标题: grid中的某一列默认为文本框,根据需要动态的变更为下拉框,且支持动态变更数据源 需求是这样的: 有一些参数(A),这些参数又分别对应另外的参数(B),所以,先把A作为一列,B根据A ...
- html制作,点击文字超链接显示文本框,再点击文字超链接隐藏文本框
</head><body> <script> window.onload=function(){ document.getElementById('click'). ...
- input文本框实现宽度自适应代码实例,input文本框
本章节介绍一下如何让一个文本框的宽度能够随着文本框中的内容的宽度增长而增长,也就是能够实现宽度自适应效果. 代码实例如下: <!DOCTYPE html> <html> < ...
- jquery 文本框失去焦点显示提示信息&&单击置空文本框
1.<textarea rows="4" placeholder="请输入提醒内容"></textarea> 2. /** * @par ...
- jqgrid 表格中筛选条件的多选下拉,树形下拉 ;文本框清除插件;高级查询多条件动态筛选插件[自主开发]
/** * @@desc 文本框清除按钮,如果isAutoWrap为false当前文本框父级必须是relative定位,boostrap参考input-group * @@author Bear.Ti ...
- Silverlight中文本框添加回车事件后,换行无法清除的解决方法
在开发Silverlight的项目中,为了更好的用户体验,我们常要给一些控件添加一些快捷键.然而,在Silverlight中当用户回车提交后,光标停留在文本框的第二行怎么也清除不掉,经过一段时间研究, ...
- 文本框的onchange事件,如何兼容各大浏览器
在项目中经常会遇到对用户输入的数据进行实时校验,而不是等文本框失去焦点或用户手动点击校验. 首先分析下在哪些情况下文本框会产生change事件. 1.用户通过键盘入正常字符时: 2.用户通过键盘输入非 ...
- 机房收费系统总结之4——VB.NET 轻松解决判断文本框、组合框为空问题
纵观机房收费系统,判断文本框.组合框为空问题无非两种情况.第一种:判断窗体中所有文本框.组合框是否为空.第二种:判断一部分文本框.组合框是否为空.下面看看是如何实现这两种情况的. 第一种:判断窗体中所 ...
- xmlplus 组件设计系列之三 - 文本框
文本框是页面中最常用的输入组件,它的默认使用方式如下: <input type='text'/> 当然,这里的 `type='text' 可以略去不写.大部分情况下,使用默认的文本框作为输 ...
随机推荐
- 使用 StringUtils.split 的坑
点赞再看,动力无限. 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. 在日常的 Java 开发中,由于 J ...
- 如何免安装使用 Python?推荐 17 个在线的 Python 解释器!
作者:Al Sweigart 译者:豌豆花下猫@Python猫 英文:https://inventwithpython.com/blog/2022/10/30/17-online-python-ide ...
- 4.drf-版本管理
根据RESTful规范,后端API中需要体现出版本,DRF中支持5种版本的设置,常见的三种如下 1. URL的GET中传递参数 在视图类中定义 from rest_framework.versioni ...
- Vue 基础学习总结
介绍 Vue.js 中文文档地址:https://cn.vuejs.org/guide/introduction.html#what-is-vue Vue.js 是什么 Vue (读音 /vjuː/, ...
- 一个jsqlparse+git做的小工具帮我节省时间摸鱼
背景 前些时间做了个小工具解决了团队内数据库脚本检验&多测试环境自动执行的问题,感觉挺有意思,在这跟大家分享一下. 工具诞生之前的流程是这样: 1.开发人员先在开发环境编写脚本&执行: ...
- Linux 中的内部命令和外部命令
Linux 中的内部命令和外部命令 作者:Grey 原文地址: 博客园:Linux 中的内部命令和外部命令 CSDN:Linux 中的内部命令和外部命令 什么是 bash shell ? bash s ...
- JDK动态代理深入剖析
1 基于接口的代理模式 什么是代理? 简单来说,代理是指一个对象代替另一个对象去做某些事情. 例如,对于每个程序员来说,他都有编程的能力: interface Programmable { void ...
- 【Advanced Installer】打包winfrom程序出现您没有任何数字签名的实用程序。请安装平台 SDK。错误
出现这个问题的原因是设置了磁铁,此功能只会在win8.1上有效.也就是开始菜单里面的磁铁图 只需要把这个删除掉就可以解决了
- 学生管理系统Python
student1=[ {1:'lucy','age':17,'sex':'n','Pnum':1111111}, {2:'tom','age':17,'sex':'m','Pnum':2222222} ...
- 伙伴福利,100个项目彻底精通Java!【开源】
为了帮助更多的小伙伴,快速成长进步,冲进大厂中厂,我分享了很多的项目哟,例如: java项目精品实战案例 | JavaSwing实战项目 但很多小伙伴,还觉得不够,好吧!今天就拿出压箱底的项目,给支持 ...