Introduction
It’s a very common practice that whenever anyone starts writing a WPF application for the first time, he/she finds it quite similar with traditional Windows Form application and hence writes all the code in code behind. But after passing few days, the code becomes huge and unmanageable.
After passing few days with WPF, people get to learn about its data binding feature which reduces the code in code behind a little bit.
It is possible to reduce the code in code behind to a great extent if we use Model View ViewModel (MVVM) design pattern. This design pattern actually utilizes WPF data binding feature and provides a good separation of concern. Thus the view (XAML) can be separately developed/designed to some extent by some other person while the core developer can concentrate on business logic. I am not going into details of MVVM, details can be learnt from here.
Now this separation of concern can be further enriched if we use the power of Unity dependency injection container. Dependency injection is a prime technique for building loosely coupled applications. It provides ways to handle the dependencies between objects. For example, an object that processes customer information may depend on other objects that access the data store, validate the information, and check that the user is authorized to perform updates. Dependency injection techniques can ensure that the customer class correctly instantiates and populates all of these objects, especially where the dependencies may be abstract. You can learn more about Unity from here.
The concept and working procedure of Unity Dependency Injection container may seem magic from Aladdin's genie on the first sight.
Like handling genie, Unity DI container needs to be handled carefully and intelligently. This article mainly covers how we can use this magic easily with some sample code example. (For your convenience, I have attached the full code base of sample application discussed here.)
Here, mainly I have discussed constructor injection and property injection so that people can use it as a quick reference.
The Unity dependency container may be regarded as a “Bank” of useful objects. Usually in bank we save our money so that we can use it in time when it is needed.
So on application initialization, we shall store all those objects that will be needed by various window/user control, etc. during the application life cycle like below:
IUnityContainer container = new UnityContainer();
container.RegisterType<IDataServices, TextDataServices>();
container.RegisterType<ITextViewModel, TextViewModel>();
var window = container.Resolve<MainWindow>();
window.Show();
In our application we have one TextDataServices
which mainly returns an hardcoded string
and we have a TextViewModel
in which we have only one string
property that is supposed to be set in some UI Label. In MainWindow.XAML, we have two Label
controls, one in left (LabelLeft
) and one in right (LabelRight
) like below:
<Label Content="{Binding Path=LabelContnet,FallbackValue=Left}"
Height="28" HorizontalAlignment="Left" Margin="90,85,0,0"
Name="LabelLeft" VerticalAlignment="Top" Width="222" Grid.ColumnSpan="2" />
<Label Content="{Binding Path=LabelContnet,FallbackValue=Right}"
Grid.Column="1" Height="28" HorizontalAlignment="Left"
Margin="90,85,0,0" Name="LabelRight" VerticalAlignment="Top" Width="222" />
Now let’s concentrate on the code behind of this XAML file (MainWindow.xaml.cs):
public partial class MainWindow : Window
{
public MainWindow(ITextViewModel textViewModel)
{
InitializeComponent();
Loaded += MainWindow_Loaded;
DataContext = textViewModel;
}
[Dependency]
public IDataServices Services { get; set; }
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
LabelLeft.Content = Services.GetData();
}
In the constructor, you can see that there is one parameter of type ITextViewModel
which will be injected by the Unity when this window will be resolved from OnStartUp
event of App.xaml.cs.
In the code behind file, you will also see one property of type IDataServices
which has [Dependency]
attribute on top of it.
When this window will be resolved during runtime, the object associated with IDataServices
will be injected as well. But remember that in the constructor, you will not be able to use this property as this will be injected after the constructor has been called. This type of injection is called property injection.
In order to use the benefit of property injection, you can use this property on Windows.Loaded
event or you can write some code on the set property of injectable property.
So when we shall run the code, the left label will be populated from constructor injected TextViewModel
and the right label will be populated from property injected DataServices
!
I hope this will give you an initial idea about how to use constructor injection and property injection in WPF. When you will be starting a large scale WPF application, you need to use Unity, MVVM and ultimately Prism in your application.