一、Commands
Composite Commands
情景:
上述情景中,Submit All Command的邏輯是要調用所有Submit Command的邏輯。
解決方案: Prism中提供了CompositeCommand,這個類持有一組child command,CompositeCommand在執行的時候將會調用每一個child command的Execute方法,可以通過,可以通過RegisterCommand和UnregisterCommand來註冊和註銷child command。
commandProxy.SubmitAllOrdersCommand.RegisterCommand(
orderCompositeViewModel.SubmitCommand );
commandProxy.CancelAllOrdersCommand.RegisterCommand(
orderCompositeViewModel.CancelCommand );
在當前View上執行Command
情景:
在上面的應用中,放大縮小按鈕應該只對當前的活動視圖(active view)起作用,而對其它視圖不起作用。
解決方案: Prism提供了IActiveAware接口,它包含了IsActive屬性和IsActiveChanged事件。DelegateCommand實現了這個接口,CompositeCommand下面的構造函數能夠使得在執行child command的時候只執行所有的active command。
public CompositeCommand(bool monitorCommandActivity);
集合中的Command
情景:
這個問題的關鍵是,在每一個Item中點擊“Delete”實際上是改變它的parent view中view model的集合,問題的難點在於,每個Item的data context是集合本身的一項,而不是實現了Delete Command的parent view model。
解決方案:
使用ElementName屬性指定綁定是相對於它的parent control,而不是相對於data template。
<Grid x:Name="root">
<ListBox ItemsSource="{Binding Path=Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Path=Name}" Command="{Binding ElementName=root,
Path=DataContext.DeleteCommand}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
可以使用CommandParameter指明當前應用的item,也可以實現command來獲取當前選中的item(通過CollectionView)。
二、交互
在很多時候,應用程序都會通知用戶當前狀態或者在處理一個請求之前需要用戶的確認,在非MVVM模式中,很通用的方式就是在Code-behind文件中使用MessageBox類進行交互,然而在MVVM模式中,這種做法就不合適了,因爲這會使得部分view model邏輯放到了view中。
在MVVM模式中,通常有兩種方法可以實現這種交互,一種方法是實現一個由view model使用的service來觸發用戶交互,另一種方法是由view model 觸發一個事件來進行交互。
使用Interaction Service
這種方法是使得view model依賴於interaction service進行用戶交互,interaction service實現交互的可視化部分。
var result =
interactionService.ShowMessageBox(
"Are you sure you want to cancel this operation?",
"Confirm",
MessageBoxButton.OK );
if (result == MessageBoxResult.Yes)
{
CancelRequest();
}
使用Interaction Request Object
這種方法是view model將交互請求直接發給view本身,請求對象封裝封裝請求和回覆的所有細節,並且通過event和view通信,view通過behavior綁定到view model提供的request object。
Prism採用這種方式,並且提供了IInteractionRequest接口和InteractionRequest<T>類。
public interface IInteractionRequest
{
event EventHandler<InteractionRequestedEventArgs> Raised;
}
public class InteractionRequest<T> : IInteractionRequest
{
public event EventHandler<InteractionRequestedEventArgs> Raised;
public void Raise(T context, Action<T> callback)
{
var handler = this.Raised;
if (handler != null)
{
handler(
this,
new InteractionRequestedEventArgs(
context,
() => callback(context)));
}
}
}
Prism同時提供了上下文類,用作交互傳遞。Notification類是這些類的基類,Confirmation類繼承自Notification用於實現類似MessageBox類型的交互請求。
下面的代碼顯示了view model如何使用InteractionRequest<T>。
public IInteractionRequest ConfirmCancelInteractionRequest
{
get
{
return this.confirmCancelInteractionRequest;
}
}
this.confirmCancelInteractionRequest.Raise(
new Confirmation("Are you sure you wish to cancel?"),
confirmation =>
{
if (confirmation.Confirmed)
{
this.NavigateToQuestionnaireList();
}
});
}
在view層次,prism提供了InteractionRequestTrigger,這個類能自動連接到IInteractionRequest接口的Raised 事件,
<i:Interaction.Triggers>
<prism:InteractionRequestTrigger
SourceObject="{Binding ConfirmCancelInteractionRequest}">
<prism:PopupChildWindowAction
ContentTemplate="{StaticResource ConfirmWindowTemplate}"/>
</prism:InteractionRequestTrigger>
</i:Interaction.Triggers>
<UserControl.Resources>
<DataTemplate x:Key="ConfirmWindowTemplate">
<Grid MinWidth="250" MinHeight="100">
<TextBlock TextWrapping="Wrap" Grid.Row="0" Text="{Binding}"/>
</Grid>
</DataTemplate>
</UserControl.Resources>