2010-08-25 153 views
5

我正在開發一個Silverlight LoB應用程序,設計人員希望有一個標籤界面,類似於Visual Studio的界面(我們可能會使用Telerik Rad控件作爲對接標籤)。完成原型之後,界面運行良好,但我在考慮如何在MVVM項目中實現撤銷/重做功能時遇到問題。如何在MVVM應用程序中實現撤銷/重做?

撤消/恢復功能有:

  1. 上的撤消/重做,UI狀態,即 返回焦點,選擇等恢復到 控制(一個或多個)(例如一個文本框) 這個變化源於。
  2. 擁有按次撤銷/重做堆棧

通常情況下,我會用命令的模式,但我不知道如何應用與MVVM。

我已經使用了命令&綁定來獲得理想化的視圖模型的鬆散耦合,但它使撤銷/重做變得更加棘手,因爲視圖模型沒有任何視圖的概念以及接收到命令或綁定屬性發生變化時的視圖狀態。似乎我需要某種服務跟蹤,無論何時用戶執行一些可撤銷操作並獲取狀態以供以後恢復時,該視圖都處於活動狀態。

對於在MVVM中實現撤消/重做的最佳實踐有什麼共識嗎?我非常關心丹尼爾沃恩如何在他的鈣項目中做到這一點; Blend顯然是使用MVVM模式編寫的,它的行爲與我想要的應用程序一樣,如果MS解釋他們是如何做到的,那就太棒了!

回答

2

您需要做的第一件事是確保您完全將操作與界面分開。這意味着將影響數據的所有操作轉換爲離散操作。這也意味着無論是什麼原因導致觀點轉變,也應該記錄爲一個獨立的行動。基本上,界面的狀態應該只反映數據更改和基於命令的視圖更改(請參閱下面有關視圖更改的最後一個註釋)。

我們以前使用過的最成功的撤消系統允許嵌套IUndoableCommand對象。這些複合命令彙總爲單個用戶操作(您希望在「撤消」菜單中顯示的那種操作)。

我注意到你提及在視圖中使用撤消...這似乎是一個多種應用程序的不尋常的行爲。通常,撤消操作僅在單個控件和任何拖放操作中進行。例外通常是基於圖形的接口(不是基於表單的)。在撤消過程中更改表單將等同於MS Word切換到另一個文檔並繼續撤銷...對最終用戶非常不利。可能想讓用戶體驗人員重新考慮設計的這一方面。只是我的2美分價值。

希望這會有所幫助。

+0

我現在也將根據你提到的調查鈣項目。感謝那。 – 2010-08-25 18:02:44

+0

感謝您的回答,HiTech。當你說「撤銷僅在單個控件中」時,你的意思是,例如,在一個帶有幾個文本框的窗體(視圖)上,用戶必須關注一個文本框,在該文本框中爲他進行更改以撤銷/重做他通過TextBox所做的任何更改?將操作與接口完全分開 - 是否意味着禁止視圖中的控件與視圖模型中的屬性之間的雙向綁定?不幸的是,我們的應用程序具有交互式繪圖表面(畫布)和Blend/VS等形式;這很複雜。 絕對感謝您的想法! – JamesCo 2010-08-26 13:26:56

1

@JamesCo,

我實現了撤銷/重做一個WPF應用程序,並最終發佈我的撤銷/重做代碼http://muf.codeplex.com/。你也可以通過NuGet獲取它。只需查找「MUF」或「受監視的撤消框架」即可。它包括對Silverlight 4.0以及.NET 3.5,4.0和WP7的支持。

我的WPF應用程序也使用MVVM,在某些情況下,確實允許撤消選擇更改等操作。我還跟蹤了WPF框架中顯示的活動「頁面」,以便用戶移回到撤消操作應該應用的頁面。

該庫採用靈活的方法來編寫撤消/重做每個步驟的操作。最終,它只需要一個代表撤消和一個代表重做。你可以讓這些代表做你喜歡的任何事情。庫中包含一個默認的實現,它只是簡單地使用對象,屬性名稱,舊值和新值。它構建基於反射的代表,根據需要應用舊值或新值。

就隔離每個視圖的更改而言,該庫允許爲每個「文檔」或「容器」保留單獨的撤消/重做操作堆棧。您只需傳遞對容器的引用即可獲得關聯的撤銷/重做堆棧。

最後,該庫包含對批處理更改的支持。在多個行動應該作爲一個整體撤回的時候,這很有用。

歡迎對codeplex網站(http://muf.codeplex.com/)提出意見和問題。您還會在那裏找到完整的文檔和示例應用程序。