Prism,IConfirmNavigationRequest,InteractionRequest和Async

时间:2015-10-01 14:45:11

标签: wpf mvvm prism-5

我有一个问题,我将我的视图,viewmodel创建编码到ModuleInit.Initialize方法

this.container.RegisterType<IControlPanel, ViewModels.SeveritiesViewModel>("SeveritiesViewModel");
this.container.RegisterType<object, Views.SeveritiesView>("SeveritiesView", new InjectionConstructor(new ResolvedParameter<IControlPanel>("SeveritiesViewModel")));

SeveritiesVeiwModel继承自ViewModelBase

public class ViewModelBase : BindableBase, IControlPanel, INavigationAware, IConfirmNavigationRequest

ViewModelBase的构造函数调用两个虚方法。 Initialize和GetData。 GetData使用async await执行一些数据访问方法。

所以我遇到的问题是Prism构造我的SeveritiesViewModel,GetData方法运行,并抛出我捕获的异常。然后我想使用InteractionRequest显示一个对话框,但是尚未设置view.DataContext,因此没有绑定或Interaction.Triggers接收InteractionRequest。

所以我想我应该使用回调查看RegionManager.RequestNaviagte。我认为,因为我的所有视图模型都实现了IConfirmNavigationRequest,所以我可以在注入的View / viewmodel中返回NavigationResult中的false。但是从不调用ConfirmNavigationRequest。这是wpf不是silverlight?

那么我如何处理这个非常分离的应用程序。我需要实现某种类型的共享服务吗? 我想我将需要存储异常,直到视图完成与viewmodel的绑定,也许实现我自己的接口与方法来检查异常集合和在视图中调用接口方法? 为什么从未调用ConfirmNavigationRequest?

在DataContext设置之后,InteractionRequest工作得很好,但之前;我不知所措。

任何建议将不胜感激。

由于 加里

这是一些代码。

工具栏按钮命令单击运行以下内容。

this.regionManager.RequestNavigate("ContentRegion", "SeveritiesView");

这是视图背后的代码。

public partial class SeveritiesView : UserControl, IApplicationView
{
    public SeveritiesView(IControlPanel model)
    {
        InitializeComponent();
        this.DataContext = model;
    }

    public string ViewName
    {
        get { return "SeveritiesView"; }
    }
}

ViewModelBase。

        protected ViewModelBase(bool initializeDB = true) 
    {
        notifications = new List<NotificationWindowNotification>();
        this.uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
        NotificationRequest = new InteractionRequest<NotificationWindowNotification>();
        ConfirmationRequest = new InteractionRequest<ConfirmationWindowNotification>();
        if (initializeDB)
        {
            EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
            entityBuilder.ProviderConnectionString = EventLogAnalysis.Properties.Settings.Default.ConnectionString;
            db = new ServerEventLogEntities(entityBuilder.ToString());
        }
        ThrobberVisible = Visibility.Visible;
        Initialize();
        GetData();
    }

SeveritiesViewModel。

 public SeveritiesViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) : base()
    {
        try
        {
            this.regionManager = regionManager;
            this.eventAggregator = eventAggregator;
            eventAggregator.GetEvent<AddSeverity>().Subscribe(AddSeverity);
            eventAggregator.GetEvent<DeleteSeverity>().Subscribe(DeleteSeverity);
        }
        catch(Exception e)
        {
                 uiFactory.StartNew(() =>
                NotificationRequest.Raise(new NotificationWindowNotification()
                {
                    Title = string.Format("Error during {0}.{1}"
                        , ModuleName, System.Reflection.MethodBase.GetCurrentMethod().Name),
                    Content = string.Format("{0}", e.Message)
                })
            ).Wait();
        }

    }

protected async override void GetData()
    {
        try
        {
            List<Task> tasks = new List<Task>();
            tasks.Add(GetEventFilterSeverities());

            await Task.WhenAll(tasks).ContinueWith((t) =>
            {
                ThrobberVisible = Visibility.Collapsed;
                eventAggregator.GetEvent<RecordStatusEvent>().Publish(new RecordStatusMessage() { CanAdd = true, CanDelete =(currentEventFilterSeverity != null), IsClosing = false });
            }
            , TaskScheduler.FromCurrentSynchronizationContext());
        }
        catch(Exception e)
        {
           notifications.Add(new NotificationWindowNotification()
                {
                    Title = string.Format("Error during {0}.{1}"
                        , ModuleName, System.Reflection.MethodBase.GetCurrentMethod().Name),
                    Content = string.Format("{0}", e.Message)
                });
        }

    }

protected async Task GetEventFilterSeverities()
    {
        try
        {
            throw new NullReferenceException("My exception");
            ObservableCollection<EventFilterSeverity> _eventFilterSeverities = new ObservableCollection<EventFilterSeverity>();
            var eventFilterSeverities = await (from sg in db.EventFilterSeverities
                                        orderby sg.EventFilterSeverityID
                                        select sg).ToListAsync();
            foreach (EventFilterSeverity efs in eventFilterSeverities)
                _eventFilterSeverities.Add(efs);
            EventFilterSeverities = _eventFilterSeverities;
        }
        catch(Exception e)
        {
            notifications.Add(new NotificationWindowNotification()
                {
                    Title = string.Format("Error during {0}.{1}"
                        , ModuleName, System.Reflection.MethodBase.GetCurrentMethod().Name),
                    Content = string.Format("{0}", e.Message)
                });
        }

    }

2 个答案:

答案 0 :(得分:0)

两个相当简单的解决方案;

  1. 在显示Shell并且可以进行交互之前,不要启动数据访问
  2. 在交互请求可用时完成的await上捕获异常并立即Task。这是导航完成时的情况吗?这有效地将交互排队,以便何时可以显示。

答案 1 :(得分:0)

这看起来很有希望。 在视图中

addDays(-1)

在ViewModelBase

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Raised" SourceObject="{Binding NotificationRequest}">
        <i:EventTrigger.Actions>
            <dialogs:PopupWindowAction IsModal="True"/>
        </i:EventTrigger.Actions>
    </i:EventTrigger>
    <i:EventTrigger EventName="Loaded">
        <ei:CallMethodAction TargetObject="{Binding Mode=OneWay}" MethodName="DisplayPreBoundExceptions"/>
    </i:EventTrigger>
</i:Interaction.Triggers>