2015-12-18 1 views
4

J'utilise un Messenger class afin d'envoyer des données entre les modèles de vue. Il y a un AppView qui héberge deux vues principales dans un contrôle de contenu, et jusqu'ici n'ont eu aucun problème avec envoyer/recevoir des données de cette façon.Comment enregistrer un gestionnaire de message avant l'appel de blocage ShowDialog()?

Problème:

Maintenant, j'ajouté un ProductView qui affiche une boîte de dialogue séparée au APPVIEW. Mais quand j'appelle Messenger.Default.Send<ProductModel>(SelectedProduct); après avoir appelé. ShowDetailDialog() cela bloque l'appel de code Send, jusqu'à ce que la boîte de dialogue soit fermée.

J'ai essayé l'inverse en appelant d'abord le code Send, puis en ouvrant la boîte de dialogue. Mais cela signifie que le gestionnaire de messages de la machine virtuelle réceptrice ne s'enregistre pas à temps avant l'envoi du message.

Est-ce que quelqu'un sait d'une solution, pour empêcher la boîte de dialogue de bloquer l'appel d'envoi? Ou enregistrez-vous le gestionnaire de messages ProductVM avant d'envoyer un message et d'afficher une boîte de dialogue?

Ci-dessous un résumé des classes liées:

CustomerOrdersVM (envoi du code):

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

ProductVM (code de réception):

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 (Main VM sont enregistrés, ProductVM est indépendant de cette machine virtuelle):

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: (détient les vues 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> 

Répondre

2

Vous pourrait résoudre le problème de plusieurs façons:

  1. N'utilisez pas ShowDialog(). Utilisez Show() et faites en sorte que la fenêtre de dialogue TopMost apparaisse dans la fenêtre principale.
  2. Enregistrez le ProductView dans le constructeur de la DialogService (avez-vous vraiment besoin d'un nouveau ProductView chaque fois de toute façon?)

  3. Faire la DialogService (ou une classe utilitaire à l'intérieur de celui-ci) s'inscrire au moment de la construction du message , puis passer le message à tout affiché ProductView s

Personnellement, j'aime # 2 puisque vous utilisez ShowDialog, cela implique que seul ProductView est jamais nécessaire à la fois.Par exemple:

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

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

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

bien dans # 2, par le registre ProductView, voulez-vous dire passer dans le cteur comme ceci: DialogService public (vue ProductView) {} this._view = vue ensuite appeler pourriez également vous fournir un extrait sur la solution n ° 1, rendant la boîte de dialogue parentale à appView? –

+0

J'ai donné un exemple de # 2 dans une édition. Pour # 1, voir https://msdn.microsoft.com/en-us/library/system.windows.window.topmost(v=vs.110).aspx et http://stackoverflow.com/questions/27462682/ wpf-set-parent-window –

+0

J'ai implémenté # 2 en enregistrant ProductView dans DialogService(). Alors .. _productView.ShowDialog(); n'a pas fonctionné, mais pour une raison quelconque _productView.Show(); a travaillé. Des idées pourquoi c'est? –