2

我正在實現由多個平臺上的應用程序共享的視圖模型。我正在使用具有自己的MvxEventToCommand類的MvvmCross v3,但我相信其他框架(如MVVM Light)的挑戰是相同的。只要事件沒有參數就可以使用,實現就很順利,簡單的交互就是這種情況,比如點擊控件。EventToCommand與便攜式視圖模型中的參數綁定

但是當命令需要處理事件參數時事情變得更加複雜。例如,視圖模型需要對某些滾動條更改進行操作(並在關聯的列表視圖中加載更多項目)。這裏是XAML的例子:

<cmd:EventToCommand 
    Command="{Binding ScrollChanged}" 
    CommandParameter="{Binding EventArgs}" /> 

(MvvmCross使用MvxEventToCommand,但原理是一樣的)。

然後在我的模型,我可以有下面的命令處理程序:

public ICommand ScrollChanged 
{ 
    get 
    { 
     return new RelayCommand<ScrollChangedEventArgs>(e => 
     { 
      MessageBox.Show("Change!"); 
     }); 
    } 
} 

(MvxCommand在MvvmCross)。

問題是ScrollChangedEventArgs是特定於平臺的,並且此代碼根本無法在便攜式類庫中編譯。這是任何命令的一般問題,當事件被觸發時不僅需要推送,而且需要更具體的事件細節。將這些代碼移植到平臺特定的部分是很愚蠢的,因爲它或多或少地殺死了可移植視圖模型和無代碼視圖的概念。我試圖搜索在不同平臺之間共享視圖模型的項目,但它們都使用簡單的事件,如「點擊」,沒有附加事件詳細信息。

更新1我同意斯圖爾特的言論是查看模型應具有更高層次的抽象處理,所以我會改寫原有的關注:如何將低級別的交互的結果映射到觸發一個平臺中立的事件業務邏輯命令?考慮上面的例子:業務邏輯命令是「在列表中加載更多項目」,即我們處理列表虛擬化,其中來自大集合的有限數量的項目最初被加載,並且滾動到列表的底部應該導致需要加載其他項目。

WinRT可以通過使用支持ISupportIncrementalLoading接口的可觀察集合來處理列表虛擬化。運行時檢測到此功能,並在用戶向下滾動列表時自動請求來自各個服務的額外項目。在其他平臺上,此功能應該手動實現,除了在ScrollViewer ScrollChanged事件上作出反應之外,我找不到任何其他方式。我可以看到然後另外兩個選項:

  • 地點OnScrollChanged處理程序代碼隱藏文件,並調用所述便攜式視圖模型更高級別的事件(諸如「OnItemsRequested」);
  • 避免代碼隱藏的東西,並努力將ScrollChanged事件直接連接到視圖模型,然後我們需要首先重新映射特定於平臺的事件。

只要沒有第二個選項的支持,只要事件映射的唯一目的完成事件處理程序在代碼隱藏文件中即可。但我想調查使用第二種方法可以做些什麼。 MvvmCross有MapCommandParameter類,它似乎能夠提供幫助,所以我想知道是否應該利用那個。

UPDATE 2我嘗試過MapCommandParameter方法,它工作允許我插入一個特定於平臺的適配器,它可以映射低級別事件以查看特定於模型的命令。所以第二個選擇沒有任何掙扎。斯圖爾特還提出了listview-subclassing,所以不需要關心滾動事件。我打算以後再玩。

回答

2

我同意viewmodel命令通常應該用viewmodel的概念來表達 - 所以發送viewmodel一個關於滾動條值變化的命令會很奇怪,但是可能會發送viewmodel命令用戶選擇某些列表元素是可見的(她通過滾動來做)

以前我做過這種事情的一個例子是列表選擇。

這是上WindowsPhone的(例如)經由一個EventToCommand類然後使用像https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.WindowsPhone/Commands/MvxSelectionChangedEventToCommand.cs

-

我原先使用的跨平臺EventArgs對象這樣做跨多個平臺

但是...我不得不承認,這段代碼還沒有被使用太多...對於列表選擇,我們主要使用selecteditem綁定,並且根本沒有任何應用程序需要更復雜的參數化命令(到目前爲止) - 您甚至可能需要返回到非常舊的v1 mvvmcross代碼來查找使用它的任何樣本。

+0

謝謝@Stuart,我已經擴展了這篇文章,並告訴我如何理解這可以實現。基本上,它是將事件映射器放入代碼隱藏或使用MvvmCross MapCommandParameter類的一種選擇。我完全同意平臺特定的事件細節不屬於視圖模型。 – 2013-04-07 14:25:54

+0

無法回答 - 飛機起飛時間。但爲了加載更多,可以考慮子類化listview,以便它可以觸發loadmore命令而不是滾動事件。我認爲這大概是什麼教程pulltorefresh – Stuart 2013-04-07 15:00:55

+0

我會嘗試這兩種選擇,只是爲了看看什麼看起來更乾淨。感謝您的建議。 – 2013-04-07 19:00:56