Reputation: 555
Using: WPF, Prism 5, Unity
I am trying to write what I call a "WindowDialogService" which, when passed a type and called, will open a Window with that type as the content. My problem is I cannot get the ViewModel to instantiate and associate to the View.
I don't know if it is right but I am using AutoWireViewModel
in my View and was assuming (obviously incorrectly) that the ViewModel would be "Located" when resolving using the Unity Container i.e. container.TryResolve <T> ()
So basically, I can resolve the View but the DataContext of the view is null.
I have included all relevant code below.
View
<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 Implementation
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;
}
}
}
}
Upvotes: 0
Views: 874
Reputation: 10863
Prism 6 does this automatically, for Prism 5 you need something along the lines of
ViewModelLocationProvider.SetDefaultViewModelFactory( type => Container.Resolve( type ) );
in your bootstrapper's ConfigureContainer
Upvotes: 1