2016-07-19 1 views
0

En utilisant: WPF, Prisme 5, UnitéPrism 5 et Unity - manuellement résoudre View avec ViewModel câblé

Je suis en train d'écrire ce que j'appelle un "WindowDialogService" qui, lorsqu'il est passé un type et appelé, ouvrira une fenêtre avec ce type comme contenu. Mon problème est que je ne peux pas obtenir le ViewModel à instancier et associer à la vue.

Je ne sais pas si elle est juste, mais je me sers AutoWireViewModel à mon avis et assumait (évidemment à tort) que le ViewModel serait « Situé » lors de la résolution en utilisant le conteneur Unity à savoir container.TryResolve <T>()

Donc, fondamentalement, , Je peux résoudre la vue mais le DataContext de la vue est nul.

J'ai inclus tout le code pertinent ci-dessous.

Voir

<dxc:DXWindow x:Class="ListClassList.Views.AddToClassView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:prism="http://prismlibrary.com/"  
       prism:ViewModelLocator.AutoWireViewModel="True" 
       xmlns:dxe="clr-namespace:DevExpress.Xpf.Editors.Settings;assembly=DevExpress.Xpf.Core.v15.2" 
       xmlns:dxeditors="http://schemas.devexpress.com/winfx/2008/xaml/editors" 
       xmlns:dxc="http://schemas.devexpress.com/winfx/2008/xaml/core" 
       xmlns:dxgt="http://schemas.devexpress.com/winfx/2008/xaml/grid/themekeys" 
      xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"    
      xmlns:extToolkit="http://schemas.xceed.com/wpf/xaml/toolkit" 
        WindowStartupLocation="CenterScreen" 
        dxc:ThemeManager.ThemeName="VS2010" 
        Title="{Binding Title}" 
        Width="800" 
        Height="500" 
       ResizeMode="CanResizeWithGrip" 
      > 
    <Grid> 
    </Grid> 
</dxc:DXWindow> 

ViewModel

using MyApp.Data; 
using MyApp.Models.Model; 
using Prism.Commands; 
using Prism.Mvvm; 
using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Linq; 
using System.Windows; 

namespace ListClassList.ViewModels 
{ 
    public class AddToClassViewViewModel : BindableBase 
    { 
     private readonly MyAppDbContext _context; 

     private ObservableCollection<MasterClass> _masterClasses; 
     public ObservableCollection<MasterClass> MasterClasses 
     { 
      get { return _masterClasses; } 
      set { SetProperty(ref _masterClasses, value); } 
     } 

     private ObservableCollection<Student> _students; 
     public ObservableCollection<Student> Students 
     { 
      get { return _students; } 
      set 
      { 
       SetProperty(ref _students, value); 
      } 
     } 


     public DelegateCommand FinishCommand { get; set; } 


     public AddToClassViewViewModel(IStudentTimetableService studentTimetableService) 
     { 


     } 

    } 
} 

IWindowDialogService Interface

using System; 
using System.Windows; 
    namespace MyApp.Infrastructure.Services.Dialogs.WindowDialog 
    { 
     public interface IWindowDialogService 
     { 
      bool? ShowDialog<T>(Action onDialogClosed) where T : Window; 
     } 
    } 

WindowDialogService mise en œuvre

using System; 
using System.Collections.Generic; 
using System.Windows; 
using Microsoft.Practices.ServiceLocation; 
using Prism.Unity; 


namespace MyApp.Infrastructure.Services.Dialogs.WindowDialog 
{ 
    public sealed class WindowDialogService : IWindowDialogService 
    { 
     private readonly List<Window> _openWindows = new List<Window>(); 
     private static volatile WindowDialogService _instance; 
     private static readonly object SyncRoot = new Object(); 

     private WindowDialogService() { } 

     public static WindowDialogService Instance 
     { 
      get 
      { 
       if (_instance == null) 
       { 
        lock (SyncRoot) 
        { 
         if (_instance == null) 
          _instance = new WindowDialogService(); 
        } 
       } 
       return _instance; 
      } 
     } 


     public bool? ShowDialog<T>(Action onDialogClosed) where T : Window 
     { 
      try 
      { 
       using (var container = new Microsoft.Practices.Unity.UnityContainer()) 
       { 
        var dialog = (Window)container.TryResolve <T>(); 
        dialog.Closed += (s, e) => onDialogClosed(); 
        var result = dialog.ShowDialog(); 
        return result; 
       } 

      } 
      catch (Exception) 
      { 

       throw; 
      } 
     } 
    } 
} 

Répondre

2

Prism 6 fait automatiquement, pour Prism 5 vous besoin de quelque chose le long des lignes de

ViewModelLocationProvider.SetDefaultViewModelFactory(type => Container.Resolve(type)); 

dans votre de bootstrapper

+0

Merci Haukinger. J'ai essayé mais ça ne semble pas régler le problème. Y a-t-il autre chose que je dois changer dans mon code? J'ai mis cette ligne de code (exactement comme indiqué) dans mon ConfigureContainer dans mon programme d'amorçage. Est-ce que la façon dont je résous la vue (en train de créer un UnityContainer et en utilisant TryResolve) est correcte? –

+0

J'utiliserais le conteneur one unity du bootstrapper (faites-le injecter en tant que dépendance de votre service), juste au cas où votre fenêtre aurait ses propres dépendances. Et, bien sûr, toutes les dépendances de votre modèle de vue doivent être enregistrées avec le conteneur utilisé pour résoudre le modèle de vue. – Haukinger

+0

Ok, mon mauvais! * Dumb * J'ai récemment mis à jour vers Prism 6, ce qui a entraîné un changement de version que la View ne peut pas terminer en "View" (et ViewModels ne peut pas se terminer en "ViewViewModel".) Voir ici: github.com/PrismLibrary/Prism. comme la réponse correcte vu comme il adresse la question comme demandé ;-) –