Prism应用开发(六)——MVVM高级话题

一、Commands

Composite Commands

情景:


上述情景中,Submit All Command的逻辑是要调用所有Submit Command的逻辑。

解决方案: Prism中提供了CompositeCommand,这个类持有一组child command,CompositeCommand在执行的时候将会调用每一个child command的Execute方法,可以通过,可以通过RegisterCommand和UnregisterCommand来注册和注销child command。

  1. commandProxy.SubmitAllOrdersCommand.RegisterCommand(  
  2. orderCompositeViewModel.SubmitCommand );  
  3. commandProxy.CancelAllOrdersCommand.RegisterCommand(  
  4. orderCompositeViewModel.CancelCommand );  
commandProxy.SubmitAllOrdersCommand.RegisterCommand(
orderCompositeViewModel.SubmitCommand );
commandProxy.CancelAllOrdersCommand.RegisterCommand(
orderCompositeViewModel.CancelCommand );

在当前View上执行Command

情景:


在上面的应用中,放大缩小按钮应该只对当前的活动视图(active view)起作用,而对其它视图不起作用。

解决方案: Prism提供了IActiveAware接口,它包含了IsActive属性和IsActiveChanged事件。DelegateCommand实现了这个接口,CompositeCommand下面的构造函数能够使得在执行child command的时候只执行所有的active command。

  1. public CompositeCommand(bool monitorCommandActivity);  
public CompositeCommand(bool monitorCommandActivity);

集合中的Command

情景:

这个问题的关键是,在每一个Item中点击“Delete”实际上是改变它的parent view中view model的集合,问题的难点在于,每个Item的data context是集合本身的一项,而不是实现了Delete Command的parent view model。

解决方案:

使用ElementName属性指定绑定是相对于它的parent control,而不是相对于data template。

  1. <Grid x:Name="root">  
  2. <ListBox ItemsSource="{Binding Path=Items}">  
  3. <ListBox.ItemTemplate>  
  4. <DataTemplate>  
  5. <Button Content="{Binding Path=Name}" Command="{Binding ElementName=root,  
  6. Path=DataContext.DeleteCommand}" />  
  7. </DataTemplate>  
  8. </ListBox.ItemTemplate>  
  9. </ListBox>  
  10. </Grid>  
<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实现交互的可视化部分。

  1. var result =  
  2. interactionService.ShowMessageBox(  
  3. "Are you sure you want to cancel this operation?",  
  4. "Confirm",  
  5. MessageBoxButton.OK );  
  6. if (result == MessageBoxResult.Yes)  
  7. {  
  8. CancelRequest();  
  9. }  
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>类。

  1. public interface IInteractionRequest  
  2. {  
  3. event EventHandler<InteractionRequestedEventArgs> Raised;  
  4. }  
  5. public class InteractionRequest<T> : IInteractionRequest  
  6. {  
  7. public event EventHandler<InteractionRequestedEventArgs> Raised;  
  8. public void Raise(T context, Action<T> callback)  
  9. {  
  10. var handler = this.Raised;  
  11. if (handler != null)  
  12. {  
  13. handler(  
  14. this,  
  15. new InteractionRequestedEventArgs(  
  16. context,  
  17. () => callback(context)));  
  18. }  
  19. }  
  20. }  
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>。

  1. public IInteractionRequest ConfirmCancelInteractionRequest  
  2. {  
  3. get  
  4. {  
  5. return this.confirmCancelInteractionRequest;  
  6. }  
  7. }  
  8. this.confirmCancelInteractionRequest.Raise(  
  9. new Confirmation("Are you sure you wish to cancel?"),  
  10. confirmation =>  
  11. {  
  12. if (confirmation.Confirmed)  
  13. {  
  14. this.NavigateToQuestionnaireList();  
  15. }  
  16. });  
  17. }  
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 事件,

  1. <i:Interaction.Triggers>  
  2. <prism:InteractionRequestTrigger  
  3. SourceObject="{Binding ConfirmCancelInteractionRequest}">  
  4. <prism:PopupChildWindowAction  
  5. ContentTemplate="{StaticResource ConfirmWindowTemplate}"/>  
  6. </prism:InteractionRequestTrigger>  
  7. </i:Interaction.Triggers>  
  8. <UserControl.Resources>  
  9. <DataTemplate x:Key="ConfirmWindowTemplate">  
  10. <Grid MinWidth="250" MinHeight="100">  
  11. <TextBlock TextWrapping="Wrap" Grid.Row="0" Text="{Binding}"/>  
  12. </Grid>  
  13. </DataTemplate>  
  14. </UserControl.Resources>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值