我們正在創建一個大量使用高度裝飾的輸入元素的WPF應用程序。裝飾元素的一個簡單示例是TextBox,它在沒有焦點時看起來像只讀TextBlock,並在接收焦點後變爲TextBox。另外,當更改的值被保存到數據庫時會提供額外的視覺反饋。問題是,顯示一個包含很多這些元素的視圖(比方說100)非常慢,並且使應用程序非常無響應。如何在WPF中懶洋洋地創建UI元素?
我們已經實現了這個裝飾器作爲用戶控件,它包含所有必需的元素(例如TextBlock顯示未聚焦的文本和旋轉圖像忙標誌)。然後,我們將輸入元素添加爲此裝飾器控件的子元素,這意味着除了所有額外的元素之外,裝飾器還在其可視化樹中包含輸入元素。在XAML,這將是這樣的:
<custom:Decorator Context="{Binding ValueHelper}" >
<TextBox Text="{Binding ValueHelper.Text}"/>
</custom:Decorator>
這很容易讓我們來裝點我們想要的任何輸入元素,無論是任何一個文本框中,日期選擇器,組合框或任何自定義元素。
現在回到問題:比方說,我們有一個視圖,其中包含100個裝飾文本框,我們導航到該視圖。怎麼了?至少我的四核筆記本電腦凍結很長一段時間,因爲它必須創建許多文本塊,矩形,圖像等,以提供每個裝飾元素的視覺反饋,儘管沒有裝飾品可見但。真正需要的僅僅是100個TextBlocks,因爲這是屏幕上可見的。只有在元素接收到鼠標懸停事件後,或者在需要其他元素時才關注。而且,一次只能編輯一個元素,因此只有一個輸入元素(在這種情況下是文本框)對於整個應用程序就足夠了。
那麼,如何在不爲視圖中的每個元素創建所有裝飾元素(或實際輸入元素)的情況下實現相同裝飾的最佳方式是什麼?
裝飾文本框,以澄清使用情況的一個例子:
文本框時像沒有焦點或鼠標光標,只讀TextBlock的目前並未在它的上面(狀態1)。此外,還顯示了三個點(「...」),因爲元素不會有任何價值。
當鼠標光標移動到元素的頂部時,TextBlock周圍出現一個綠色的虛線矩形,表示該元素可以被修改(狀態2)。如果TextBox碰巧是隻讀的,顏色將會變成紅色。
接收聚焦元件後變成可用於修改的實際值(狀態3)實際文本框。
文本框失去它的焦點之後,並表明,該值正在被保存忙指示符顯得元件(狀態4)的左邊的值存儲到數據庫中。
最後,該值已被保存和元件返回到表示新的值(狀態5)它的空閒狀態。 (實際上這些元素有更多的狀態與驗證和其他特定要求有關,但是您肯定知道元素真的是高度裝飾的。)
謝謝!控件模板絕對是裝飾元素的方式。但是,這並不能解決實際輸入元素的問題。 TextBox是我們最輕的元素,我們有更重的自定義輸入元素(例如日期選擇器),我們無法創建。我們已經設置了可見性來摺疊,但仍然會創建可視化樹,並加載所有相關資源,這會導致嚴重的性能問題。 – user544511 2013-03-28 08:04:43
@ user544511當你說「所有相關資源被加載」時,你的意思是每個裝飾器都被加載了嗎?因爲如果你使用的裝飾一個UI控制和換出的模板,因爲只有一個元素在視覺樹同時 – Rachel 2013-03-28 11:52:10
對不起,我正在度假,不能剛纔的答覆存在,你不應該讓這種行爲。我的意思是創建了實際的輸入元素(這是裝飾器的子元素,例如日期選取器或文本框),它的所有資源(包括子元素)都被加載並添加到可視樹中(即使它已摺疊)。這導致巨大的性能下降,因爲日期選擇器的元素比例如重量要大得多。一個文本框。 – user544511 2013-04-02 11:08:57