【问题标题】:Prism Custom Confirmation InteractionPrism 自定义确认交互
【发布时间】:2016-02-06 08:01:28
【问题描述】:

我使用 Prism Unity、WPF 和 Mvvm 在应用程序中创建了一个自定义确认窗口。我需要有关需要发送回视图模型的通知的帮助。我在详细记录视图中有这个,我们称之为 MyDetailView。

<!-- Custom Confirmation Window -->
<ie:Interaction.Triggers>
  <interactionRequest:InteractionRequestTrigger 
       SourceObject="{Binding ConfirmationRequest, Mode=TwoWay}">
     <mycontrols:PopupWindowAction1 IsModal="True"/>
  </interactionRequest:InteractionRequestTrigger>
</ie:Interaction.Triggers>

如上图,我设置了交互Mode=TwoWay,这样确认弹窗就可以返回OK或者Cancel按钮的点击结果。确认窗口按原样出现,但我不知道如何将按钮单击结果发送回我的视图模型,比如 MyDetailViewModel。这是主要问题。

编辑:这是引发 InteractionRequest 的 MyDetailViewMmodel 方法。

private void RaiseConfirmation()
{ConfirmationRequest
    .Raise(new Confirmation()
    {
        Title = "Confirmation Popup",
        Content = "Save Changes?"
    },  c =>{if (c.Confirmed)
{ UoW.AdrTypeRos.Submit();}

这是 PopupWindowAction1 类。这个问题的部分答案可能是我如何实现 Notification 和 FinishedInteraction 方法。

class PopupWindowAction1 : PopupWindowAction, IInteractionRequestAware
{
    protected override Window GetWindow(INotification notification)
    { // custom metrowindow using mahapps
        MetroWindow wrapperWindow = new ConfirmWindow1();
        wrapperWindow.DataContext = notification;
        wrapperWindow.Title = notification.Title;

        this.PrepareContentForWindow(notification, wrapperWindow);

        return wrapperWindow;
    }

    public INotification Notification
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }

    public Action FinishInteraction
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }
}

我需要在我的 ConfirmWindow1 中进行一些交互吗?

<i:Interaction.Triggers>
  <i:EventTrigger EventName="PreviewMouseLeftButtonUp">
    <ei:CallMethodAction 
      TargetObject="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, 
        Path=DataContext}"
      MethodName="DataContext.ValidateConfirm"/>
  </i:EventTrigger>
</i:Interaction.Triggers>

我什至需要在按钮中进行这种类型的交互吗?如果是这样,我如何编写它需要的代码,以便它对应于调用交互的特定视图模型。有什么建议么?谢谢。

【问题讨论】:

    标签: wpf mvvm notifications prism interaction


    【解决方案1】:

    主要的是,当您提出交互时,提供一个在交互完成时触发的回调。此回调会返回通知,并且您的交互应该已将所有可能感兴趣的返回值存储在那里。

    这是一个例子......

    ViewModel 的相关部分:

    public InteractionRequest<SelectQuantityNotification> SelectQuantityRequest
    {
        get;
    }
    
    // in some handler that triggers the interaction
    SelectQuantityRequest.Raise( new SelectQuantityNotification { Title = "Load how much stuff?", Maximum = maximumQuantity },
        notification =>
        {
            if (notification.Confirmed)
                _worldStateService.ExecuteCommand( new LoadCargoCommand( sourceStockpile.Stockpile, cartViewModel.Cart, notification.Quantity ) );
        } );
    

    ...从视图中:

    <i:Interaction.Triggers>
        <interactionRequest:InteractionRequestTrigger 
            SourceObject="{Binding SelectQuantityRequest, Mode=OneWay}">
            <framework:FixedSizePopupWindowAction>
                <interactionRequest:PopupWindowAction.WindowContent>
                    <views:SelectSampleDataForImportPopup/>
                </interactionRequest:PopupWindowAction.WindowContent>
            </framework:FixedSizePopupWindowAction>
        </interactionRequest:InteractionRequestTrigger>
    </i:Interaction.Triggers>
    

    此外,我们需要一个类来保存传递的数据,以及一个用于交互本身的 ViewModel/View 对。

    这是数据保存类(注意 Maximum 被传递交互,Quantity 从它返回):

    internal class SelectQuantityNotification : Confirmation
    {
        public int Maximum
        {
            get;
            set;
        }
    
        public int Quantity
        {
            get;
            set;
        }
    }
    

    这是交互弹窗的视图:

    <UserControl x:Class="ClientModule.Views.SelectSampleDataForImportPopup"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
        <StackPanel Orientation="Vertical">
            <TextBlock>
                Amount: <Run Text="{Binding Quantity}"/>
            </TextBlock>
            <Slider Orientation="Horizontal" Minimum="0" Maximum="{Binding Maximum}" Value="{Binding Quantity}" TickPlacement="BottomRight"/>
            <Button Content="Ok" Command="{Binding OkCommand}"/>
        </StackPanel>
    </UserControl>
    

    它是 ViewModel:

    internal class SelectSampleDataForImportPopupViewModel : BindableBase, IInteractionRequestAware
    {
        public SelectSampleDataForImportPopupViewModel()
        {
            OkCommand = new DelegateCommand( OnOk );
        }
    
        public DelegateCommand OkCommand
        {
            get;
        }
    
        public int Quantity
        {
            get { return _notification?.Quantity ?? 0; }
            set
            {
                if (_notification == null)
                    return;
                _notification.Quantity = value;
                OnPropertyChanged( () => Quantity );
            }
        }
    
        public int Maximum => _notification?.Maximum ?? 0;
    
        #region IInteractionRequestAware
        public INotification Notification
        {
            get { return _notification; }
            set
            {
                SetProperty( ref _notification, value as SelectQuantityNotification );
                OnPropertyChanged( () => Maximum );
                OnPropertyChanged( () => Quantity );
            }
        }
    
        public Action FinishInteraction
        {
            get;
            set;
        }
        #endregion
    
        #region private
        private SelectQuantityNotification _notification;
    
        private void OnOk()
        {
            if (_notification != null)
                _notification.Confirmed = true;
            FinishInteraction();
        }
        #endregion
    }
    

    【讨论】:

    • 谢谢。我会试试看。
    • 我有一点不同的是,我试图在 TwoWay 模式下执行 InteractionRequest。另一个是我使用 MetroWindow 作为确认弹出窗口,即。 wrapperWindow.DataContext = 通知;这将我的弹出窗口的 DataContext 设置为 InteractionRequest,因此要修改我的代码以匹配建议,当它接管为新的 DataContext 时,我需要以某种方式更新弹出窗口视图模型中的 Notification 属性。
    • TwoWay 或 OneWay 仅影响绑定,我使用 OneWay,因为我的 SelectQuantityRequest-Property 是只读的,无论如何都不需要更改。 Notification-Property 来自于实现IInteractionRequestAware,它应该由框架设置。
    • 我喜欢提供的视图模型方法,但在我的场景中,我只需要一个非常简单的确认弹出窗口,它只返回确认结果。确认弹出窗口没有可视化树,通过它我可以获得引发 InteractionRequest 的视图/视图模型的引用。所以一个选项可能是 Mode=TwoWay 绑定到自我,即。引发 InteractionRequest 的视图的视图模型中的属性。
    • 为什么需要参考?将处理程序放在触发“”交互请求的位置。你能提供更多关于这个的代码吗?此外,无论您是使用 view + viewmodel 还是仅在弹出窗口中使用代码并不重要,您可以单独保留 PopupWindowAction 并使用默认值,除非您想实际自定义窗口。但无论哪种方式,它都是实施IInteractionRequestAware 的错误位置。而是在触发器的定义中设置其PopupWindowAction.WindowContent
    猜你喜欢
    • 1970-01-01
    • 2021-07-10
    • 2017-06-15
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    • 1970-01-01
    相关资源
    最近更新 更多