如何在ShowDialog()阻塞调用之前注册消息处理程序? [英] How to register message handler prior to ShowDialog() blocking call?

查看:198
本文介绍了如何在ShowDialog()阻塞调用之前注册消息处理程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Messenger类,以便在视图模型之间发送数据。有一个 AppView 在内容控件中托管两个主要视图,直到现在,这种方式发送/接收数据都没有问题。

I'm using a Messenger class in order to send data between view models. There is an AppView that hosts two main views in a content control, and up until now have had no issue with sending/receiving data this way.

问题:

现在我添加了一个 ProductView 显示与AppView的单独对话。但是当我调用$ code> Messenger.Default.Send< ProductModel>(SelectedProduct); 后,调用.ShowDetailDialog()将阻止发送代码调用,直到对话框关闭。

Now I added a ProductView that shows a separate dialog to the AppView. But when I call Messenger.Default.Send<ProductModel>(SelectedProduct); after calling .ShowDetailDialog() this blocks the Send code call, until the dialog is closed.

我尝试了其他方式,调用发送代码先打开对话框。但是这意味着在发送消息之前,接收VM中的消息处理程序不会及时注册。有没有人知道一个解决方案,以防止对话框阻止发送呼叫?

I tried the other way around, calling the Send code first, then opening the dialog. But this means that the message handler in the receiving VM doesn't register in time before the message is sent.

或者在发送消息并显示对话框之前注册ProductVM消息处理程序?

Does anyone know of a solution, to prevent the dialog from blocking the send call? Or alternatively register the ProductVM message handler prior to sending message and showing dialog?

以下是相关类的摘要:

CustomerOrdersVM(发送代码):

    private void EditOrder(object obj)
    {
        _dialogService.ShowDetailDialog();    
        Messenger.Default.Send<ProductModel>(SelectedProduct);            
    }

ProductVM(接收代码):

    public ProductViewModel()
    {
        Messenger.Default.Register<ProductModel>(this, OnSelectedProductReceived);              
    }

DialogService:

class DialogService : IDialogService
{

    Window productView = null;

    public DialogService()
    {

    }


    public void ShowDetailDialog()
    {
         productView = new ProductView();
        productView.ShowDialog();
    }
}

AppVM(主VM已注册,ProductVM独立于此虚拟机):

    public ApplicationViewModel()
    {
        // Add available pages
        PageViewModels.Add(new CustomerDetailsViewModel(customerDataService, countryDataService, dialogService));
        PageViewModels.Add(new CustomerOrdersViewModel(orderDataService, dialogService));
        PageViewModels.Add(new OrderStatisticsViewModel());

        // Set starting page
        CurrentPageViewModel = PageViewModels[0];  
    }

AppView:(保存AppVM视图):

<Window x:Class="MongoDBApp.Views.ApplicationView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:views="clr-namespace:MongoDBApp.Views"
        xmlns:vm="clr-namespace:MongoDBApp.ViewModels">


    <Window.Resources>
        <DataTemplate DataType="{x:Type vm:CustomerDetailsViewModel}">
            <views:CustomerDetailsView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CustomerOrdersViewModel}">
            <views:CustomerOrdersView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:OrderStatisticsViewModel}">
            <views:OrderStatisticsView />
        </DataTemplate>
    </Window.Resources>

    <Window.DataContext>
        <vm:ApplicationViewModel />
    </Window.DataContext>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height=".07*" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>


        <TabControl Grid.Row="1"
                    ItemsSource="{Binding PageViewModels}"
                    SelectedItem="{Binding CurrentPageViewModel}"
                    TabStripPlacement="Top">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" />
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ItemContainerStyle>
                <Style TargetType="{x:Type TabItem}">
                    <Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
                </Style>
            </TabControl.ItemContainerStyle>
        </TabControl>
    </Grid>
</Window>


推荐答案

您可以通过以下几种方式解决问题: p>

You could solve the problem a few ways:


  1. 不要使用 ShowDialog()。使用 Show(),并将对话框窗口TopMost和父窗口放在主窗口中。

  2. 注册 ProductView 在DialogService的构造函数(你真的需要一个新的 ProductView 每次?)

  1. Don't use ShowDialog(). Use Show(), and make the dialog window TopMost and parented to the main window.
  2. Register the ProductView in the constructor of the DialogService (do you really need a new ProductView each time anyway?)

DialogService (或其中的实用程序类)在建设时注册为消息,然后将消息传递任何显示的 ProductView s

Make the DialogService (or a utility class inside of it) register at construction time for the message, and then pass the message on to any displayed ProductViews

我个人喜欢#2 - 由于您使用 ShowDialog ,这意味着一次只需要一个 ProductView 。例如:

Personally I like #2- since you are using ShowDialog, it implies that only one ProductView is ever needed at a time. For example:

class DialogService : IDialogService
{
    Window productView = null;
    ProductView _productView;

    public DialogService()
    {
         _productView = new ProductView();
    }

    public void ShowDetailDialog()
    {
        _productView.ShowDialog();
    }
}

这篇关于如何在ShowDialog()阻塞调用之前注册消息处理程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆