An easy way to do this is to create a XAML resource that will resolve your ViewModel for you, via your IoC container.
Many MVVM frameworks offer this feature, but I wanted one to specifically work with Autofac, so I have written on for this purpose.
Here’s my data provider class
public class AutofacDataProvider : DependencyObject { public static readonly DependencyProperty AutofacContainerProperty = DependencyProperty.Register("AutofacContainer", typeof(IContainer), typeof(AutofacDataProvider), new PropertyMetadata(null, AutofacValuesChanged)); public IContainer AutofacContainer { get { return (IContainer)GetValue(AutofacContainerProperty); } set { SetValue(AutofacContainerProperty, value); } } public static readonly DependencyProperty DataTypeNameProperty = DependencyProperty.Register("DataTypeName", typeof(string), typeof(AutofacDataProvider), new PropertyMetadata(null, AutofacValuesChanged)); public string DataTypeName { get { return (string)GetValue(DataTypeNameProperty); } set { SetValue(DataTypeNameProperty, value); } } private static readonly DependencyPropertyKey DataPropertyKey = DependencyProperty.RegisterReadOnly("Data", typeof(object), typeof(AutofacDataProvider), new PropertyMetadata(null)); public static readonly DependencyProperty DataProperty = DataPropertyKey.DependencyProperty; public object Data { get { return (object)GetValue(DataProperty); } private set { SetValue(DataProperty, value); } } private static void AutofacValuesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var container = d.GetValue(AutofacContainerProperty) as IContainer; var typeName = d.GetValue(DataTypeNameProperty) as string; if (container == null || string.IsNullOrEmpty(typeName)) return; var assembly = Assembly.GetExecutingAssembly(); var type = assembly.GetType(typeName, false, true); if (type == null) return; var data = container.Resolve(type); d.SetValue(DataPropertyKey, data); } }
here's an example of a viewmodel I want to instantiate
public interface IMainViewModel { string Name { get; set; } } public class MainViewModel : IMainViewModel, INotifyPropertyChanged { private string name = "test name"; public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } }
Here is where I wire up my container (you probably wouldn’t do it like this but this will do for our example)
public partial class App : Application { public static IContainer Container { get; private set; } protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var builder = new ContainerBuilder(); builder.RegisterType<MainViewModel>().As<IMainViewModel>(); Container = builder.Build(); } }
And here it is in my XAML
<Window x:Class="WpfApplication7.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:app="clr-namespace:WpfApplication7" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <app:AutofacDataProvider DataTypeName="WpfApplication7.IMainViewModel" AutofacContainer="{Binding Source={x:Static app:App.Container}}" x:Key="DataSource" /> </Window.Resources> <Grid DataContext="{Binding Source={StaticResource DataSource}, Path=Data}"> <TextBlock Text="{Binding Name}" /> </Grid> </Window>