Reputation: 1792
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?
Upvotes: 1
Views: 5717
Reputation: 6908
Follow these steps
MyWindow
and MyResource
with Autofac. 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)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).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}"/>
Upvotes: 1