最近做了一個(gè)小工具,其中用到了WPF中的TextBox控件。對(duì)于這個(gè)控件的使用,其中主要的一個(gè)功能是需要選擇指定的行,并將其顯示在控件可見(jiàn)區(qū)域的視圖中(如果不在可視區(qū)域時(shí),需要控件自動(dòng)滾動(dòng)到改行)。在我使用時(shí),發(fā)現(xiàn)一個(gè)問(wèn)題,如果當(dāng)我先將指定的行滾動(dòng)至視圖中,然后在將其選中,則經(jīng)常會(huì)不穩(wěn)定,有時(shí)能定位并選中,有時(shí)則會(huì)選中錯(cuò)誤位置,或者報(bào)錯(cuò)?,F(xiàn)在我想將我遇到的問(wèn)題以代碼的方式進(jìn)行說(shuō)明,以及我的解決方案。不過(guò),目前其原因還未搞明白,如果有高人,還請(qǐng)給予指點(diǎn)。
創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿(mǎn)足客戶(hù)于互聯(lián)網(wǎng)時(shí)代的韶山網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
首先,在自定義控件中添加一個(gè)TextBox控件,命名為txtBoxDocument,并在控件中提供兩個(gè)公共方法GoToLine(int rowIndex)和SelectedLine(int rowIndex),用來(lái)定位并滾動(dòng)至指定行和選中改行。
////// 定位到指定行 /// /// 指定的從零開(kāi)始的行的索引 public void GoToLine(int rowIndex) { txtBoxDocument.ScrollToLine(rowIndex); } ////// 選中指定的行 /// /// 指定的從零開(kāi)始的行的索引 public void SelectedLine(int rowIndex) { try { int lineLength = txtBoxDocument.GetLineLength(rowIndex); int start = txtBoxDocument.GetCharacterIndexFromLineIndex(rowIndex); txtBoxDocument.Focus(); txtBoxDocument.Select(start, lineLength); } catch { } }
然后,我們?cè)谡{(diào)用這兩個(gè)方法(假設(shè)我們使用一個(gè)Button調(diào)用,并在TextBox中指定要跳轉(zhuǎn)至的行),Button命名為:btnGoTo,該文本框命名為txtBoxLineNum
private void btnGoTo_Click(object sender, RoutedEventArgs e) { int rowIndex = 0; if(int.TryParse(txtBoxLineNum.Text,rowIndex)) { //先選擇,再跳轉(zhuǎn)至指定位置(這種使用方式?jīng)]問(wèn)題) SelectedLine(rowIndex ); GoToLine(rowIndex ); } }
如果將上面的調(diào)用方式改成下面情況,則會(huì)在SelectedLine(int rowIndex)方法的int lineLength = txtBoxDocument.GetLineLength(rowIndex);這句話(huà)出現(xiàn)問(wèn)題,得出的lineLength不一定就是指定行的文本長(zhǎng)度了,有可能是負(fù)值。錯(cuò)誤的調(diào)用方式如下:
private void btnGoTo_Click(object sender, RoutedEventArgs e) { int rowIndex = 0; if(int.TryParse(txtBoxLineNum.Text,rowIndex)) { //先跳轉(zhuǎn)定位,再選擇(這種使用方式不穩(wěn)定) GoToLine(rowIndex ); SelectedLine(rowIndex ); } }
如果將SelectedLine(int rowIndex)方法中的獲取指定行的文本長(zhǎng)度的方式改為先獲取其內(nèi)容,再計(jì)算長(zhǎng)度(int lineLength = txtBoxDocument.GetLineText(rowIndex).Length;),則經(jīng)常會(huì)報(bào)錯(cuò)。下面是改后的SelectedLine(int rowIndex):
////// 選中指定的行 /// /// 指定的從零開(kāi)始的行的索引 public void SelectedLine(int rowIndex) { try { //采用錯(cuò)誤的調(diào)用方式,下面這句話(huà)會(huì)報(bào)錯(cuò)(錯(cuò)誤信息如下面貼出的圖片所示) int lineLength = txtBoxDocument.GetLineText(rowIndex).Length; int start = txtBoxDocument.GetCharacterIndexFromLineIndex(rowIndex); txtBoxDocument.Focus(); txtBoxDocument.Select(start, lineLength); } catch { } }
錯(cuò)誤內(nèi)容:當(dāng)前方法的代碼已經(jīng)過(guò)優(yōu)化,因此無(wú)法計(jì)算表達(dá)式的值。
但是,采用正確的調(diào)用順序的方式不論是GetLineText(rowIndex).Length方式獲取指定行的文本長(zhǎng)度還是使用GetLineLength(rowIndex)方式獲取指定行的文本長(zhǎng)度,都是沒(méi)問(wèn)題的。具體緣由尚不明確,也沒(méi)有查到相關(guān)的資料介紹。我自己的理解是在進(jìn)行ScrollToLine(rowIndex)操作之前,先選中指定行的文本,此時(shí),文本內(nèi)容沒(méi)有進(jìn)行滾動(dòng),是個(gè)靜止的狀態(tài),當(dāng)先進(jìn)行滾動(dòng)在去選中指定文本,文本內(nèi)容是個(gè)動(dòng)態(tài)滾動(dòng)的,可能此時(shí).NET運(yùn)行時(shí)需要做某些處理,因此,此時(shí)去獲取指定行的文本長(zhǎng)度或文本內(nèi)容則容易出現(xiàn)問(wèn)題。另外,認(rèn)為文本內(nèi)容滾動(dòng)之后對(duì)于在可視范圍內(nèi)顯示的文本相對(duì)于文本框的上邊界的距離發(fā)生了變化,這也有可能是一個(gè)因素。不知道猜測(cè)是否正確,還希望各位大俠、專(zhuān)家給予指正,也好將其原理分享給其他程序員朋友。