WPF中下拉框可作選擇項(xiàng)也可以作為只讀文本框使用的方法
1、需求
當(dāng)前在開(kāi)發(fā)的系統(tǒng)需要一個(gè)這樣的控件。
(1)可以選擇已有的選擇項(xiàng),類(lèi)似于ComboBox選擇;
(2)可以通過(guò)其他按鈕點(diǎn)擊,選擇一個(gè)文件,選擇后,把文件路徑顯示到控件上,并且處于只讀狀態(tài),行為和只讀狀態(tài)下的TextBox保持一致。
更直觀些,就是實(shí)現(xiàn)類(lèi)似ArcMap中Toolbox中的數(shù)據(jù)集選擇下拉框,如下圖所示。
該控件可以通過(guò)下拉的方式,選擇左側(cè)的圖層數(shù)據(jù),又可以通過(guò)點(diǎn)擊右側(cè)的打開(kāi)文件按鈕,彈出打開(kāi)文件對(duì)話框,選擇要設(shè)置的數(shù)據(jù)文件。該控件還可以通過(guò)鍵盤(pán)輸入,但我們的需求是禁止輸入,只能選擇和通過(guò)打開(kāi)文件對(duì)話框設(shè)置。
2、現(xiàn)有的ComboBox
我計(jì)劃在WPF中的ComboBox控件的基礎(chǔ)上進(jìn)行開(kāi)發(fā),首先看通過(guò)簡(jiǎn)單的屬性設(shè)置是否能夠滿(mǎn)足要求。
(1)不設(shè)置任何參數(shù)
在不設(shè)置任何參數(shù)的情況下,效果如下圖所示。
可以顯示底圖上加載的數(shù)據(jù),但點(diǎn)擊【Select】按鈕,通過(guò)設(shè)置ComboBox.Text屬性,數(shù)據(jù)顯示不出來(lái),這種效果離我們想要的還差十萬(wàn)八千里。
(2)設(shè)置ComboBox.IsEditable=true
下面我們嘗試通過(guò)設(shè)置ComboBox的屬性看能不能達(dá)到我們想要的效果。首先把ComboBox.IsEditable屬性設(shè)置為true,然后測(cè)試下Text屬性設(shè)置后是否有效果了。
目前可以把選擇的文件路徑設(shè)置到ComboBox.Text了,并且可以正常顯示,但鼠標(biāo)點(diǎn)上去,文本框的內(nèi)容可以修改,這不是我們想要的。于是發(fā)現(xiàn)ComboBox有個(gè)IsReadOnly屬性,把該屬性設(shè)置為true嘗試一下試試。
目前下拉框中的內(nèi)容不能修改了,但實(shí)際操作的時(shí)候會(huì)發(fā)現(xiàn)有些別扭。當(dāng)鼠標(biāo)點(diǎn)擊下拉框,該控件得到焦點(diǎn)的時(shí)候,里面的文字默認(rèn)處于全選狀態(tài),此時(shí)想拖動(dòng)鼠標(biāo),把文字拖動(dòng)到尾部是操作不了的,只能再次點(diǎn)擊下拉框中的內(nèi)容,才可以和普通文本框的操作一樣通過(guò)鼠標(biāo)拖動(dòng)視圖。
經(jīng)過(guò)各種嘗試,發(fā)現(xiàn)當(dāng)ComboBox控件GotFocus的時(shí)候,里面的文字會(huì)默認(rèn)處于全選狀態(tài),這個(gè)我們需要解決一下。
3、使用VisualTreeHelper單獨(dú)處理TextBox
在網(wǎng)上查詢(xún),發(fā)現(xiàn)ComboBox在IsEditable=true的狀態(tài)下,是有很多個(gè)控件組合而成的。如下圖所示。
我們可以調(diào)用VisualTreeHelper,獲取這個(gè)TextBox,不過(guò)需要在Load后,再調(diào)用,不然這些控件是獲取不到的。
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激活后,文字全選的問(wèn)題。代碼如下。
myTextBox.GotFocus += (m, n) => { myTextBox.SelectionOpacity = 0; this._IsNeedClearSelection = true; };
該代碼的的作用是當(dāng)TextBox得到焦點(diǎn)后,立刻把TextBox中文字選中的背景顏色的透明度設(shè)置為0,這樣操作者就感覺(jué)不出來(lái)文字被選中了。
鼠標(biāo)左鍵彈起前,需要清空選中文字,并把光標(biāo)放到鼠標(biāo)點(diǎn)擊處,并還原文本選中的顏色,代碼如下。
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; };
此時(shí),基本上ComboBox能夠滿(mǎn)足我們的需求了,效果如下圖所示。
但還有一個(gè)問(wèn)題,就是在ComboBox在IsEditable=true的狀態(tài)下,鼠標(biāo)移動(dòng)到可選項(xiàng)上的時(shí)候,選擇項(xiàng)不高亮了。為了解決這個(gè)問(wèn)題,嘗試了很多方法,都不行,準(zhǔn)備放棄,就這樣了。
因?yàn)橄到y(tǒng)使用了DEV for WPF UI庫(kù),忽然想到了WPF DEV中的ComboBoxEdit,之前測(cè)試過(guò),通過(guò)設(shè)置屬性,滿(mǎn)足不了需求。但沒(méi)有使用VisualTreeHelper深入的去測(cè)試,那就再?lài)L試下看看。
4、使用WPF DEV中的ComboBoxEdit
測(cè)試的時(shí)候,ComboBoxEdit在任何屬性都不設(shè)置的情況下,除了文字可以編輯,其他的都可以滿(mǎn)足要求。于是我設(shè)置IsReadOnly=True,但這個(gè)時(shí)候,下拉框中的可選擇項(xiàng)都處于不可用狀態(tài),也不能選擇,所以IsReadOnly屬性不能設(shè)置成True。嘗試了一下有可能性的其他屬性,例如EditMode等,都不能滿(mǎn)足需求。
但在測(cè)試ComboBox的時(shí)候,知道了WPF的可視化樹(shù)這個(gè)概念,可以通過(guò)VisualTreeHelper獲取組成控件的子控件。于是加載后,在Load事件中,我們查看下ComboBoxEdit組織樹(shù),如下圖所示。
我看到了里面有個(gè)TextBox控件,這個(gè)就是顯示文本的控件了,感覺(jué)是不是獲取到這個(gè)TextBox后,把該TextBox設(shè)置成只讀是不是問(wèn)題就完美解決了?
這個(gè)樹(shù)比較深,我就找了一段根據(jù)類(lèi)型獲取元素的代碼,如下圖所示。
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和設(shè)置其屬性的代碼如下。
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; }; } }
啟動(dòng)測(cè)試,效果非常完美,正是我們需要的,界面如下圖所示。
5、總結(jié)
最開(kāi)始測(cè)試Dev中的ComboBoxEdit,通過(guò)設(shè)置屬性各種嘗試,發(fā)現(xiàn)滿(mǎn)足不了需求。既然ComboBoxEdit滿(mǎn)足不了需求,那就在WPF原生態(tài)的ComboBox上測(cè)試吧。
在ComboBox嘗試的時(shí)候,也是設(shè)置ComboBox的屬性,各種測(cè)試后,發(fā)現(xiàn)還是不行。在網(wǎng)上搜索的時(shí)候,發(fā)現(xiàn)可以通過(guò)VisualTreeHelper獲取組成ComboBox的UI樹(shù),從而對(duì)其內(nèi)部的控件進(jìn)行操作。VisualTreeHelper之前也用過(guò),但這次確實(shí)沒(méi)往這塊想。
通過(guò)VisualTreeHelper獲取ComboBox中的TextBox,通過(guò)各種嘗試,終于達(dá)到了一個(gè)比較滿(mǎn)意的效果,此時(shí)已經(jīng)花了一下午的時(shí)間。晚上下班回家后,想把這個(gè)過(guò)程整理一下,使用的時(shí)候,發(fā)現(xiàn)ComboBox在IsEditable=true的狀態(tài)下,鼠標(biāo)移動(dòng)到可選項(xiàng)上的時(shí)候,選擇項(xiàng)不高亮了。于是想把這個(gè)問(wèn)題再解決下,以達(dá)到最完美效果。
但花了兩個(gè)小時(shí)左右,一點(diǎn)思路也沒(méi)有,在網(wǎng)上也沒(méi)找到相關(guān)的資料。此時(shí)忽然想到,此前測(cè)試Dev中的ComboBoxEdit時(shí)候,還沒(méi)想到VisualTreeHelper這個(gè)方法,所以還沒(méi)測(cè)試,那就測(cè)試下看看。
于是修改了代碼,查看了下ComboBoxEdit的可視化樹(shù),發(fā)現(xiàn)里面有個(gè)TextBox,此時(shí)感覺(jué)希望非常大,因?yàn)楫?dāng)時(shí)放棄ComboBoxEdit是因?yàn)轱@示的內(nèi)容可編輯,又不能設(shè)置ComboBoxEdit的IsReadOnly屬性為T(mén)rue。現(xiàn)在看到ComboBoxEdit里面有個(gè)TextBox,就感覺(jué)八九不離十了。如果獲取到TextBox,把這個(gè)TextBox的IsReadOnly屬性為T(mén)rue不就可以了?
于是按照這個(gè)思路嘗試了一下,最后效果非常完美,完全滿(mǎn)足系統(tǒng)要求。
到此這篇關(guān)于WPF中下拉框可作選擇項(xiàng)也可以作為只讀文本框使用的方法的文章就介紹到這了,更多相關(guān)WPF下拉框使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解C#實(shí)現(xiàn)在Excel單元格中應(yīng)用多種字體格式
在Excel中,可對(duì)單元格中的字符串設(shè)置多種不同樣式。本文,將以C#及VB.NET代碼為例,介紹如何在Excel同一個(gè)單元格中應(yīng)用多種字體樣式,感興趣的可以了解一下2022-05-05C#正則表達(dá)式Regex類(lèi)用法實(shí)例分析
這篇文章主要介紹了C#正則表達(dá)式Regex類(lèi)用法,實(shí)例分析了其中比較常見(jiàn)的幾類(lèi)用法,具有一定的實(shí)用價(jià)值,需要的朋友可以參考下2014-10-10.net2.0+ Winform項(xiàng)目實(shí)現(xiàn)彈出容器層
在實(shí)際工作中,如果能像菜單一樣彈出自定義內(nèi)容,會(huì)方便很多,比如查詢(xún)時(shí),比如下拉列表顯示多列信息時(shí),比如在填寫(xiě)某個(gè)信息需要查看一些信息樹(shù)時(shí)。這個(gè)時(shí)候自定義彈出界面就顯的非常重要了2015-08-08對(duì)int array進(jìn)行排序的實(shí)例講解
下面小編就為大家分享一篇對(duì)int array進(jìn)行排序的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12SQLite之C#版 System.Data.SQLite使用方法
這篇文章主要介紹了SQLite之C#版 System.Data.SQLite使用方法,需要的朋友可以參考下2020-10-10C#通過(guò)Semaphore類(lèi)控制線程隊(duì)列的方法
這篇文章主要介紹了C#通過(guò)Semaphore類(lèi)控制線程隊(duì)列的方法,涉及Semaphore類(lèi)操作線程隊(duì)列的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08