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

查看:29
本文介绍了如何在 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 显示一个单独的对话框.但是当我在调用 .ShowDetailDialog() 之后调用 Messenger.Default.Send<ProductModel>(SelectedProduct); 这会阻止 Send 代码调用,直到对话框关闭.

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.

我尝试了相反的方法,首先调用 Send 代码,然后打开对话框.但这意味着接收 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);              
    }

对话服务:

class DialogService : IDialogService
{

    Window productView = null;

    public DialogService()
    {

    }


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

AppVM(已注册主 VM,ProductVM 独立于该 VM):

    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>

推荐答案

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

You could solve the problem a few ways:

  1. 不要使用 ShowDialog().使用 Show(),使对话窗口 TopMost 并作为主窗口的父窗口.
  2. 在DialogService的构造函数中注册ProductView(真的每次都需要一个新的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(或其中的实用程序类)在构造时为消息注册,然后将消息传递给任何显示的 ProductViews

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天全站免登陆