WPF中下拉框可作选择项作为只读文本框怎么使用
导读:本文共4044.5字符,通常情况下阅读需要13分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: 1、需求当前在开发的系统需要一个这样的控件。(1)可以选择已有的选择项,类似于ComboBox选择;(2)可以通过其他按钮点击,选择一个文件,选择后,把文件路径显示到控件上,并且处于只读状态,行为和只读状态下的TextBox保持一致。更直观些,就是实现类似ArcMap中Toolbox中的数据集选择下拉框,如下图所示。该控件可以通过下拉的方式,选择左侧的图层数据,... ...
目录
(为您整理了一些要点),点击可以直达。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)=>{varmyMainGrid=VisualTreeHelper.GetChild(this,0);varmyTextBox=VisualTreeHelper.GetChild(myMainGrid,4)asTextBox;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;}varmyPosition=n.GetPosition(myTextBox);intmySelectionStart=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设置成只读是不是问题就完美解决了?
这个树比较深,我就找了一段根据类型获取元素的代码,如下图所示。
publicstaticList<T>FindVisualChild<T>(DependencyObjectpDependencyObject)whereT:DependencyObject{List<T>myTList=newList<T>{};for(inti=0;i<VisualTreeHelper.GetChildrenCount(pDependencyObject);i++){DependencyObjectmyChild=VisualTreeHelper.GetChild(pDependencyObject,i);if(myChild!=null&&myChildisTmyT){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);}}}returnmyTList;}
获取TextBox和设置其属性的代码如下。
publicclassDatasetComboBoxExUI:ComboBoxEdit{publicDatasetComboBoxExUI(){this.Loaded+=(x,y)=>{List<TextBox>myTextBoxList=VisualTreeExHelper.FindVisualChild<TextBox>(this);if(myTextBoxList.Count==0){return;}varmyTextBox=myTextBoxList[0];myTextBox.IsReadOnly=true;myTextBox.IsReadOnlyCaretVisible=true;};}}
启动测试,效果非常完美,正是我们需要的,界面如下图所示。
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
WPF中下拉框可作选择项作为只读文本框怎么使用的详细内容,希望对您有所帮助,信息来源于网络。