简体   繁体   中英

Resolving dependencies in XAML using Autofac

I have a class MyResource in my application that looks like this:

public class MyResource : IMyResource
{
    // ... whatever ...
}

And when I initialize my application in App.xaml.cs I have something like that using Autofac:

builder.Register<IMyResource>(container => new MyResource());

Now I need to add a StaticResource in a Window of my WPF application, something like this:

<Window.Resources>
    <local:MyResource x:Key="MyResource" />
</Window.Resources>

But of course, the whole idea is not to reference a concrete instance of MyResource here. Moreover, I may need to use an instance of MyResource in different Window s or UserControl s across my application. So I would like to use an instance of MyResource as a StaticResource for my Window that is resolved through the Autofac container. How can I achieve this?

I was thinking of adding the resource in the code-behind of my Window , but it may create a dependency on my container which I don't want.

I was also thinking of doing something like that in App.xaml.cs, when I initialize the application:

App.Current.MainWindow.Resources.Add("MyResource", container.Resolve<IMyResource>());

But when I use the resource in my XAML

<ListBox ItemsSource="{Binding Source={StaticResource ResourceKey=MyResource}}"/>

I get an XAMLParseException which inner exception's message stating that the resource named MyResource cannot be found. And even if it was working, I feel like it's a bit smelly.

So how can this be achieved? Is it only possible? If not what are the best way to implement this?

Follow these steps

  • Register MyWindow and MyResource with Autofac.
  • Place IMyResource in the constructor of MyWindow (Yes, you are modifying the code behind, but you are not referring to your container. If you cannot have code in the Code-behind -- perhaps you are a UserControl --then make sure someone is setting the DataContext somewhere)
  • Set DataContext to your concrete instance of IMyResource (in the constructor), or if you are using MVVM, place the instance into your viewmodel (which would also be registered with Autofac).
  • Resolve MyWindow

In code:

MyWindow(IMyResource myResource) : this()
{
  DataContext = myResource;
}

If you are using a ViewModel (also registered with Autofac):

MyWindow(MyViewModel viewModel) : this()
{
  DataContext = viewModel;
}

Add this line to your XAML:

<Window.DataContext><local:IMyResource></Window.DataContext>

Or this:

<Window.DataContext><local:MyViewModel></Window.DataContext>

And then your markup for ListBox becomes trivial:

<ListBox ItemsSource="{Binding}"/>

Or, with the viewmodel, as the property Items , for instance, it's just as nice:

<ListBox ItemsSource="{Binding Items}"/>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM