如何在ShowDialog()阻塞调用之前注册消息处理程序



我使用Messenger类在视图模型之间发送数据。有一个AppView在一个内容控件中承载两个主要视图,到目前为止,它还没有以这种方式发送/接收数据的问题。

问题:

现在,我向AppView添加了一个ProductView,它显示了一个单独的对话框。但是,当我在调用.ShowDetailDialog()之后调用Messenger.Default.Send<ProductModel>(SelectedProduct);时,这会阻止Send代码调用,直到对话框关闭。

我尝试了另一种方法,先调用Send代码,然后打开对话框。但这意味着接收虚拟机中的消息处理程序在发送消息之前没有及时注册。

有人知道防止对话框阻止发送呼叫的解决方案吗?或者在发送消息和显示对话框之前注册ProductVM消息处理程序?

以下是相关类别的摘要:

客户订单虚拟机(发送代码):

    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>

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

  1. 不要使用ShowDialog()。使用Show(),并使对话框窗口成为TopMost并成为主窗口的父窗口
  2. 在DialogService的构造函数中注册ProductView(你真的每次都需要一个新的ProductView吗?)

  3. 使DialogService(或其内部的实用程序类)在构建时为消息注册,然后将消息传递到任何显示的ProductView

就我个人而言,我喜欢#2——因为您使用的是ShowDialog,这意味着一次只需要一个ProductView。例如:

class DialogService : IDialogService
{
    Window productView = null;
    ProductView _productView;
    public DialogService()
    {
         _productView = new ProductView();
    }
    public void ShowDetailDialog()
    {
        _productView.ShowDialog();
    }
}

最新更新