Dot Net For All

Different Ways to Bind WPF View And View Model

How to bind View and View model in WPF or how to set DataContext of View? In this article I will discuss about the different ways to bind the View and View Model in WPF. In one of my article I have discussed about the MVVM pattern in the WPF and its various components (i.e. View, View Model and Model). If you want to learn about the data binding in WPF you can learn here. This code examples are written C# programming language.

There are two ways in which we can bind View and View Model.

  1. Binding using View First Approach
  2. Binding using ViewModel First Approach

View First Approach

There are two ways by which we can bind the View and View model in View First approach.

 public class TaskViewModel
    {
        public TaskViewModel()
        {
            AllProcess = new ObservableCollection(Process.GetProcesses());
        }

        public ObservableCollection AllProcess { get; set; }
    }

Please note that I have not used any Model here. In the above case there is no model as I am getting all the process in the View Model only. The view for this project is as shown below code.

<Window x:Class="CollectioViewSource.MainWindow"         
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"       
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
        xmlns:local="clr-namespace:CollectioViewSource"        
        xmlns:system="clr-namespace:System.Diagnostics;assembly=System" 
        mc:Ignorable="d"     
        Title="MainWindow" 
        Height="350"
        Width="525">
    <Window.Resources>
        <DataTemplate DataType="{x:Type system:Process}">
            <Border BorderThickness="1" BorderBrush="Black" Width="200">
                <StackPanel>
                    <TextBlock Text="{Binding ProcessName}"></TextBlock>
                    <TextBlock Text="{Binding Id}"></TextBlock>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Column="0" Grid.Row="1">
            <ListBox ItemsSource="{Binding AllProcess}" ></ListBox>
        </ScrollViewer>
    </Grid>
</Window>
 

Now to bind the ViewModel(TaskViewModel in our case) and View(MainWindow.xaml) we have to write the below code. This is the code present in the MainWindow() constructor.The above code is setting the DataContext of the MainWindow as instance of the TaskViewModel.

 public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new TaskViewModel();
        }

The ListBox is bound to the AllProcess property. This property should be present in the DataContext instance which is TaskViewModel in our case.

Now since the AllProcess is collection of type Process(System.Diagnostics). I have defined a data template for Process type.

Once the xaml parser encounters the Listbox it starts looking in the Resource Dictionaries to check for template of the Process type. If it finds it binds to it and we can see the result as shown in the last figure of article.

The other approach to bind the View and Viewmodel in View First Approach is in the xaml itself as shown in the figure below.

View View-Model Binding

I am setting the datacontext in the .xaml of the View itself. To set the datacontext in this way the ViewModel class need to have a default constructor. This is the preferable way of we not expecting any parameters for the constructor of View Model.

View Model First Approach

The next approach is to use initialize the view model first. First lets check the MainWindow.xaml code

View Model First Approach

The code behind of the MainWindow.xaml is nothing apart from the InitializeComponent() method.

The dataContext of the MainWindow.xaml is MainWindowViewModel.cs. Its code is as shown below. It has a property of type CustomerListViewModel named CurrentViewModel.

    public class MainWindowViewModel
    {
        public CustomerListViewModel CurrentViewModel { get; set; }

        public MainWindowViewModel()
        {
            CurrentViewModel = new CustomerListViewModel();
        }
    }

    public class CustomerListViewModel
    {
        private string firstSearchText;
        private string secondSearchText;
        public CustomerListViewModel()
        {
            AllProcess = new ObservableCollection<Process>(Process.GetProcesses());
        }      
        public ObservableCollection<Process> AllProcess { get; set; }
     }

This is the only code for View Model First Approach. And it is quite self explanatory. I have created a ContentControl in the MainWindow.xaml. The property to which it is bound is CurrentViewModel which is of type CustomerListViewModel in MainWindowViewModel. I have created a DataTemplate for the CustomerListViewModel data type. The DataTemplate contains a UserControl named CustomerListVIew. The code CustomerListView is as shown below

<UserControl x:Class="CollectioViewSource.CustomerListView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:system="clr-namespace:System.Diagnostics;assembly=System"
             xmlns:local="clr-namespace:CollectioViewSource"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <DataTemplate DataType="{x:Type system:Process}">
            <Border BorderThickness="1" BorderBrush="Black" Width="200">
                <StackPanel>
                    <TextBlock Text="{Binding ProcessName}"></TextBlock>
                    <TextBlock Text="{Binding Id}"></TextBlock>
                </StackPanel>
            </Border>
        </DataTemplate>
    </UserControl.Resources>
    <Grid>
        <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Column="0" Grid.Row="1">
            <ListBox ItemsSource="{Binding AllProcess}" >
            </ListBox>
        </ScrollViewer>
    </Grid>
</UserControl>

This is the control which is finally rendered in the View.

In all the three cases, the view which we get is as shown below. The only thing that is different is approach.

View

Though this approach has couple of drawbacks like we cannot control the initialisation of the view model and we cannot create an instance of the view model whose constructor has multiple parameters.

Conclusion:

For any WPF application using MVVM approach we should be aware of the ways to bind the VIew and View Model. In this article I have shown the different ways to bind the View and View Model.

To learn C# and face interview with confidence I have recommended some very good books. These books can really help you to understand .NET and C#. Below is the link:

Further Learning:

  1. WPF and MVVM: Advanced Model Treatment
  2. Practical MVVM

Top career enhancing courses you can't miss

My Learning Resource

Excel your system design interview