2010-07-06 43 views
2

我有一個TextBox,它在獲取焦點時執行SelectAll()。很棒。問題是,如果內容不適合在框中,那麼SelectAll會導致內容滾動到最後。我希望它滾動到前面,而不是 - 此框正在與數字字段一起使用。如何防止WPF編輯框滾動在程序化SelectAll上結束?

我的問題是:有可能SelectAll(),但避免滾動?

我現在有的解決方法是排隊ScrollToHome。我不太喜歡這個,因爲它會在文本呈現在另一個位置時引起流行。

public new void SelectAll() 
    { 
     base.SelectAll(); 

     // changing selection does something with a queued scroll request, so have to queue ours in the back. this still may cause a flash 
     // if a render slips through. would like to find a better way to do this. 
     Dispatcher.BeginInvoke(DispatcherPriority.Background, ScrollToHome); 
    } 

注意,ScrollToHome必須排隊這樣或者被「覆蓋」由於其他一些排隊event..I'm猜測通知更改事件內部的文本框的系統。我在源代碼中探索過,它非常複雜,無法確切地知道它在做它的滾動請求。

所以,我正在尋找的是下列之一:

  1. 如何全選()沒有任何滾動出現或與它滾動到前面。
  2. 如何強制更新顯示器,以便我不會彈出。

回答

3

包裝你SelectAll()ScrollToHome()電話與BeginChange()EndChange()。這將保存重畫:

public new void SelectAll() 
{ 
    BeginChange(); 
    SelectAll(); 
    ScrollToHome(); 
    EndChange(); 
} 

另一種選擇是失去焦點關閉您TextBox,然後再做選擇。

+0

我忘了開始/結束。這確定了它,謝謝! – scobi 2010-07-07 20:49:03

0

我有完全相同的問題(文本框,當它獲得焦點,我希望它滾動到開始而不是結束),但在Silverlight中。那裏沒有BeginChange/EndChange,所以我基本上拿出了Scott Bilas的回答。

這意味着我得到了重繪,這是令人沮喪的,但是我現在可以提出最好的。爲了讓它更駭人,只需要一個BeginInvoke是不夠的,因爲到底部的自動滾動排隊,有時發生在BeginInvoke動作之後,所以我必須引入一個人工延遲(在新線程中產生並在BeginInvoke之前10ms休眠)讓它更可靠。所以我結束了這一點:

var scrollViewer = VisualTreeWalker.FindVisualChildren<ScrollViewer>(TextBox) 
    .FirstOrDefault(); 

new Thread(delegate() 
{ 
    Thread.Sleep(10); 
    scrollViewer.Dispatcher.BeginInvoke(() => 
    { 
     scrollViewer.ScrollToLeft(); 
     scrollViewer.ScrollToTop(); 
    }); 
}).Start(); 

我做一個依賴屬性觀察者觀看的ScrollViewer的Horizo​​ntalOffset在文本框中,然後做的BeginInvoke當Horizo​​ntalOffset成爲非零出場,但這只是需要太多的特殊情況..如果文本框中沒有足夠的文本引起自動滾動,那麼Horizo​​ntalOffset保持爲0會怎麼樣?然後,應該導致滾動的合法用戶編輯將滾動回頂部/左側。它變成了一個大兔子洞,所以我不得不滿足於這種可怕的黑客攻擊。