How to register message handler prior to ShowDialog() blocking call?(如何在 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:
- 不要使用
ShowDialog().使用Show(),使对话窗口 TopMost 并作为主窗口的父窗口. 在DialogService的构造函数中注册
ProductView(真的每次都需要一个新的ProductView吗?)
- Don't use
ShowDialog(). UseShow(), and make the dialog window TopMost and parented to the main window. Register the
ProductViewin the constructor of the DialogService (do you really need a newProductVieweach 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() 阻塞调用之前注册消息处理程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在 ShowDialog() 阻塞调用之前注册消息处理程序?
- C# 中多线程网络服务器的模式 2022-01-01
- Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
- 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
- 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
- 如何用自己压缩一个 IEnumerable 2022-01-01
- WebMatrix WebSecurity PasswordSalt 2022-01-01
- MoreLinq maxBy vs LINQ max + where 2022-01-01
- 输入按键事件处理程序 2022-01-01
- 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
- C#MongoDB使用Builders查找派生对象 2022-09-04
