Click here to Skip to main content
15,867,756 members
Articles / Desktop Programming / WPF

MVVM : Event Routing to the Child ViewModel

Rate me:
Please Sign up or sign in to vote.
4.78/5 (9 votes)
26 May 2014CPOL13 min read 41.1K   820   20   7
When there is a collection of Child ViewModel then how to route the event to the ChildViewModel

Introduction

Currently, MVVM pattern is the most recommended pattern for designing the architecture of the WPF application.

MVVM principle is based on the following component:

Image 1

Generally, we design our application in the same way where there is one ViewModel for a View. ViewModel is responsible to provide/update the data and event handling for its view. It’s clear from the above diagram that for controls such as Button, ContextMenu etc there is an event handler e.g. OnButtonClickEvent defined inside the ViewModel. So on the occurrence of event such as click, registered/specified Event handler will get called.

Note: View and ViewModel Binding is done by using DataContext or Content [if Element used in XAML is ContentControl]. To develop this Sample program I have chosen the Caliburn.Micro framework. Download Caliburn.micro from here

Background/Objective

We can have a requirement, where we need one view which can be attached to the ViewModel instance from the collection of ViewModel [Multiple instances of the same type of ViewModel].

Will DataBinding and Event routing work in the expected way?

Here is the ideal pictorial representation of the scenario.

Image 2

Figure 1 : Event Routing of Event to ViewModel

So this is how we expect the application to work i.e. on the selection of child view index, Child View will get bind to the respective childviewmodel. Displayed data and the Event Routing of the Child View will be handled by the current selected ChildViewModel.

To verify the above scenario I developed the WPF application using Caliburn framework, which represents the Student Data. Based on the selected Student, application will make a call to the registered number. After doing this POC [Proof of Concept] I got the following Observation:

  • On selecting the desired Student, Student View displays the correct information like Student Name and Student Number.

Note : By default, first selected index is for Student A, later user can change it to any say B, C or A

Student A : On Clicking the Contact Button it pop up the message box saying Contacting to Student A on : XXXXXXXXX.

Image 3

Student B / C : On clicking the Contact, it shows the same Message as Contacting to Student A on: XXXXXXXXX. Same observation is noticed for Student C.

Image 4

Note: If default student is changed from A to B or C in code, then on clicking the Contact Button of any Student Message Box will display the information of the default Student.

Using the Code

Here is MainWindow View which hosts the StudentInfoView

<Window x:Class="ContactStudent.Views.MainWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
        xmlns:nsVm="clr-namespace:ContactStudent.ViewModels"
        xmlns:nsVi="clr-namespace:ContactStudent.Views"
        Title="Student Details" Height="400" Width="488" ResizeMode="NoResize" Background="DarkGray">
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="90"/>
            <RowDefinition Height="302"/>
            <RowDefinition Height="3*" />
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" Background="DarkGray">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
                <!--<Three Students i.e. A B C>-->
            <Button Name="Student_A" Grid.Column="0" Content="A" Width="110" Margin="22,22,22,28" 
                        ToolTip="Student A Information" 
                        cal:Message.Attach="[Event Click]=[Action DisplayStudentDetails('A')]"/>
            <Button Name="Student_B" Grid.Column="1" Content="B" Width="110" Margin="22,22,22,28"
                    ToolTip="Student B Information" 
                    cal:Message.Attach="[Event Click]=[Action DisplayStudentDetails('B')]"/>
            <Button Name="Student_C" Grid.Column="3" Content="C" Width="110" Margin="22,22,22,28"
                    ToolTip="Student C Information" 
                    cal:Message.Attach="[Event Click]=[Action DisplayStudentDetails('C')]"/>
        </Grid>
        <nsVi:StudentInfoView Grid.Row="1" DataContext="{Binding Student}" Background="DarkGray" HorizontalAlignment="Left"/>

    </Grid>
</Window>

Highlighted [Bold marked ]section in above code snippet shows the StudentInfoView and its DataContext Binding. It could be in the following way as well:

<ContentControl Grid.Row="1" Content="{Binding Student}" Background="DarkGray" HorizontalAlignment="Left"/>

StudentInfoView: Button Message.Attach property is highlighted using bold format.

<UserControl x:Class="ContactStudent.Views.StudentInfoView"
             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:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
             xmlns:local="clr-namespace:ContactStudent"
             mc:Ignorable="d" 
             Height="185" Width="302" Background="DarkGray">
    <Grid>
        <TextBlock Text="STUDENT'S DETAIL" TextAlignment="Center" FontWeight="Bold" Margin="64,0,96,165" />
        <TextBlock Name="Student_Name" Text="Student Name" FontWeight="Bold"                             Margin="-1,37,206,128" TextAlignment="Center"/>
        <TextBlock Name="Student" Text="{Binding StudentName}" FontWeight="Bold"                         Background="LightGray" Margin="123,35,33,128" TextAlignment="Left"/>
        <TextBlock Name="Contact_Number" Text="Phone Number" FontWeight="Bold"                           Margin="0,69,206,97" TextAlignment="Center"/>
        <TextBlock Name="Number" Text="{Binding PhoneNumber}" FontWeight="Bold"                         Background="LightGray" Margin="123,69,33,97" />
        <Button Name="Contact" Content="Contact" Margin="149,108,90,51" BorderBrush="Black" 
         cal:Message.Attach="[Event Click]=[Action OnContactClick($source, $eventArgs)]"/>      
    </Grid>
</UserControl>

MainWindowViewModel: It depicts that how StudentViewModel index selection is done under the DisplayStudentDetails(); please refer the following code.

using Caliburn.Micro;
public class MainWindowViewModel : PropertyChangedBase
{
    #region Data Member
    private static int              m_nCurrentStudentIndex = 0; //Current selected student index
    private StudentInfoViewModel[]  m_strStudentDetails; //Collection of students
    #endregion Data Member

    #region Constructor
    public MainWindowViewModel()
    {
        //allocate the memory for the Student A,B and C
        m_strStudentDetails = new StudentInfoViewModel[3];
        InitializeStudent();//Initialize StudentInfoViewModel instances to hold the information
        NotifyOfPropertyChange(() => Student);

    }
    #endregion Constructor

    #region Private Methods
    /// <summary>
    /// Initialization
    /// </summary>
    private void InitializeStudent()
    {
        int nIndex = 0;
        m_strStudentDetails[nIndex] = new StudentInfoViewModel("A", 1122334456);
        nIndex++;
        m_strStudentDetails[nIndex] = new StudentInfoViewModel("B", 1111111111);
        nIndex++;
        m_strStudentDetails[nIndex] = new StudentInfoViewModel("C", 1111111122);

    }
    #endregion Private Methods

    #region Event Handler
    /// <summary>
    /// Click Event Handler for the Button A,B and C
    /// </summary>
    /// <param name="strStudent">A/B/C</param>
    public void DisplayStudentDetails(String strStudent)
    {
        switch (strStudent)
        {
            case "A":
                m_nCurrentStudentIndex = 0;
                break;
            case "B":
                m_nCurrentStudentIndex = 1;
                break;
            case "C":
                m_nCurrentStudentIndex = 2;
                break;
        }
        NotifyOfPropertyChange(() => Student);
    }
    #endregion Event Handler

    #region Properties
    /// <summary>
    /// Get Current selected Student
    /// </summary>
    public StudentInfoViewModel Student
    {
        get
        {
            return m_strStudentDetails[m_nCurrentStudentIndex];
        }
    }
    #endregion Properties
}

DisplayStudentDetails() is the Event Handler to handle the click event of the buttons used in the MainWindowView. This handler decides the index, based on the button clicked, for the StudentInfoViewModel.

One point which is to be noted i.e. in student View displays the correct information like Name and Phone Number; it means attached viewmodel is as per the selected Student. In other words DataContxet is updating.

Then, Why Click Event of Contact Button is not routing to the attached ViewModel? Why is it always routing to the first attached ViewModel only? Is Message.Attach property updating on the change of DataContext?

Anyone or the Beginner who is trying to use the single View attached to any of the instance from the collection of ViewModel, may face the problem related to the routing the Event to correct ChildViewModel.

Problem

When a Child View is placed inside a main View and child view is binded to its ViewModel using DataContext or Content.

Main View has the option to update the Child view by selecting the index, which in turns updates the childviewodel instance [using DataContext/Content] at the run time; in this scenario change in the DataContext/Content property of Child View doesn’t update the Message.Attach property.

In another words target of the action handler of child view doesn’t get updated as per the selection gets update inside the Main view

Solutions

I am suggesting several/multiple approach to fix this issue. Each approach has its pros and cons..

Solution 1: Maintain One-To-One Mapping between View and ViewModel

This solution talks about the maintaining one-to-one mapping between View and ViewModel as depicted in below given diagram:

Image 5

Figure 2 : One-to-One mapping between View and ViewModel

Placing multiple ContentControl and binding them to their ViewModel Instances is defined inside the attached document.

This approach is very simple and easy to implement for small size application. Basically it’s about to maintain the views for each view model.

Based on the current selected index, View will be visible to the user and other view instances will be invisible; also viewmodel related to the selected view will be in action.

For my application where I have targeted only three students, I need to update the MainWindow View to hold the three ContentControl Instances for three StudentView. Based on the current selected index respective ContentControl will be visible.

MainWindowView

    <Grid Grid.Row="0" Background="DarkGray">
       <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="*"/>
       </Grid.ColumnDefinitions>
       <!--<Three Students i.e. A B C>-->
       <Button Name="Student_A" Grid.Column="0" Content="A" Width="110" Margin="22,22,22,28" 
                        ToolTip="Student A Information" 
                        cal:Message.Attach="[Event Click]=[Action DisplayStudentDetails('A')]"/>
       <Button Name="Student_B" Grid.Column="1" Content="B" Width="110" Margin="22,22,22,28"
                    ToolTip="Student B Information" 
                    cal:Message.Attach="[Event Click]=[Action DisplayStudentDetails('B')]"/>
       <Button Name="Student_C" Grid.Column="3" Content="C" Width="110" Margin="22,22,22,28"
                    ToolTip="Student C Information" 
                    cal:Message.Attach="[Event Click]=[Action DisplayStudentDetails('C')]"/>
        </Grid>
    <ContentControl Grid.Row="1" Content="{Binding StudentArr[0]}" Background="DarkGray"
                    Visibility="{Binding IsVisible[0]}"/>
    <ContentControl Grid.Row="1" Content="{Binding StudentArr[1]}" Background="DarkGray"
                    Visibility="{Binding IsVisible[1]}"/>
    <ContentControl Grid.Row="1" Content="{Binding StudentArr[2]}" Background="DarkGray"
                    Visibility="{Binding IsVisible[2]}"/> 

Highlighted [Bold marked] lines are the modifications in the MainWindowView to host the three StudentInfoView. Each ContentControl is having its own Content and Visibility property.

Note: Content property is an Object which contains the Control’s content. Because the Content property is of type Object, there are no restrictions on what you can put in a ContentControl.

MainWindowViewModel

ViewModel does also need modification to provide the Content and Visibility for each ContentControl to put the respective StudentInfoViewModel.

C#
public class MainWindowViewModel : PropertyChangedBase
    {
        #region Data Member
        private static int m_nCurrentStudentIndex = 0; //Current selected student index
        private StudentInfoViewModel[] m_strStudentDetails; //Collection of students
        private Visibility[] m_IsSelected; //Collection of Visibility Property for ContentControl element

        #endregion Data Member

        #region Constructor
        public MainWindowViewModel()
        {
            m_strStudentDetails = new StudentInfoViewModel[3]; // A,B and C
            m_IsSelected = new Visibility[3];
            InitializeStudent();//Initialize StudentInfoViewModel instances to hold the information
            vUpdateVisibility();  //Initialize the visibilty property                      
        }
        #endregion Constructor


        #region Private Methods
        /// <summary>
        /// Initialization
        /// </summary>
        private void InitializeStudent()
        {
            int nIndex = 0;
            m_strStudentDetails[nIndex] = new StudentInfoViewModel("A", 1122334456);
            nIndex++;
            m_strStudentDetails[nIndex] = new StudentInfoViewModel("B", 1111111111);
            nIndex++;
            m_strStudentDetails[nIndex] = new StudentInfoViewModel("C", 1111111122);

        }
        #endregion Private Methods


        private void vUpdateVisibility()
        {
            switch (m_nCurrentStudentIndex)
            {
                case 0:
                    m_IsSelected[0] = Visibility.Visible;
                    m_IsSelected[1] = Visibility.Hidden;
                    m_IsSelected[2] = Visibility.Hidden;
                    break;
                case 1:
                    m_IsSelected[1] = Visibility.Visible;
                    m_IsSelected[0] = Visibility.Hidden;
                    m_IsSelected[2] = Visibility.Hidden;
                    break;
                case 2:
                    m_IsSelected[2] = Visibility.Visible;
                    m_IsSelected[0] = Visibility.Hidden;
                    m_IsSelected[1] = Visibility.Hidden;
                    break;
            }
            NotifyOfPropertyChange(() => IsVisible);
        }

        #region Event Handler
        /// <summary>
        /// Click Event Handler for the Button A,B and C
        /// </summary>
        /// <param name="strStudent">A/B/C</param>
        public void DisplayStudentDetails(String strStudent)
        {
            switch (strStudent)
            {
                case "A":
                    m_nCurrentStudentIndex = 0;
                    break;
                case "B":
                    m_nCurrentStudentIndex = 1;
                    break;
                case "C":
                    m_nCurrentStudentIndex = 2;
                    break;
            }
            vUpdateVisibility();
            NotifyOfPropertyChange(() => StudentArr);
        }
        #endregion Event Handler
        /// <summary>
        /// Visibility of the ContentControl
        /// </summary>
        public Visibility[] IsVisible
        {
            get
            {
                return m_IsSelected;
            }
        }
        /// <summary>
        /// Content property value for ContentControl
        /// </summary>
        public StudentInfoViewModel[] StudentArr
        {
            get
            {
                return m_strStudentDetails;
            }
        }

    }   
    
} 

It’s clearly understood from the ViewModel implementation that I have maintained the array of Visibility and StudentInfoViewModel. DisplayStudentDetails() method decides the currently selected ContenControl. Based on the m_nCurrentStudentIndex vUpdateVisibility () set the visibility as visible for the current selection and hidden for others.

Conclusion

Placing multiple ContentControl Instances and changing their visibility has the performance advantage of only updating the control layout by forcing view to be rebuilt. In another words the ContentControl will be available in the GUI at all times and easy to be referenced in the implementation when binding properties are updated.

Using One-To-One mapping in this scenario is OK as we are dealing with 3 students only, imagine the scenario where instances are required in 1000s or more than that. What would be size of the MainWindowView.xaml?

Secondly, we are using ContentControl Framework Element. ContentControl is suitable when Content is not known till runtime. Content can be string or any Object. But In this scenario we know about the View and Object so we should avoid the usage of ContentControl when it can be replaced with other Framework element.

Thirdly, unload and load time will get increase for the child view having more controls like buttons or more UI elements.

Also it will impact the size of the application as well.

Solution 2: Access the UI Element inside the ViewModel and update the Event Handler

This Solution is about to access the UI element inside the ViewModel and based on the selected index assign the related event handler e.g. we can get the Button handle inside the ViewModel and we can change the event handler.

Following section explains how to subscribe the event handler inside the view model for a UI element. Event handler can be updated based on the current selected viewmodel. By following this approach UI Control event can be routed to the target viewmodel among the available collection of viewmodel.

Steps to Implement

a. Get the UI Element inside the ViewModel

To get the UI element inside the viewmodel one has to handle the "Loaded” event for the UserControl i.e. StudentInfoView.

C#
<UserControl x:Class="ContactStudent.Views.StudentInfoView"
             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:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
             xmlns:local="clr-namespace:ContactStudent"
             mc:Ignorable="d" 
             Height="185" Width="302" Background="DarkGray" cal:Message.Attach="[Event Loaded] = [Action vOnLoaded($Source)]" > 

Note: Event Handler is defined using Caliburn’s Message.Attach property. Also remove the click event attached for the Contact Button in StudentInforView.xaml

StudentInfoViewModel

C#
public static Button ContactBtn
{
    get;
    set;
}   

//Handles the Loaded event for the view and assign the handler for the Click Event
public void vOnLoaded(object sender)
{
    ContactBtn = ((StudentInfoView)sender).Contact;
    ContactBtn.Click += OnContactClick;   }

Highlighted part is the value for the Name property of the control i.e. Button is the control in this example and Contact is the value for the Name property.

b.Update the Event Handler for the Control’s Event e.g. Click

Considering the Student example, Contact is the button and its Click event needs update whenever there is a selection among the student. So that Click event can be routed to the targeted viewmodel. This Switching is defined inside the MainWindowViewModel as this plays the controller role for StudentInfoViewModel.

C#
/// <summary>
/// Click Event Handler for the Button A,B and C
/// <param name="strStudent">A/B/C</param>
public void DisplayStudentDetails(String strStudent)
{
   StudentInfoViewModel.ContactBtn.Click -= Student.OnContactClick;
   switch (strStudent)
   {
       case "A":
           m_nCurrentStudentIndex = 0;
           break;
       case "B":
            m_nCurrentStudentIndex = 1;
            break;
       case "C":
            m_nCurrentStudentIndex = 2;
            break;
    }
    StudentInfoViewModel.ContactBtn.Click += Student.OnContactClick;
    NotifyOfPropertyChange(() => Student);
 }

Highlighted section is the addition to the DisplayStudentDetails() method, as I have already mentioned this is the method which identify the current selected StudentInfoViewModel based on the selection is made on GUI. In general terms this routing can be defined in the eventhandler which is responsible to handle the change in selection event.

Conclusion

This implementation is about accessing the UI element inside the viewmodel, but this force the tight coupling between View and ViewModel.

For any change in the Control will force to implement the changes inside the ViewModel. This implementation is OK for small size application, means when there are not so many controls inside the UI to be handled in the same way.

Along with the increase in number of controls what if viewmodel instances are also large in number then it will require more focus on the handler registration and deregistration. This may cause crash in your application if this scenario won’t be handled properly.

You need to be very careful about the number of controls those required to be accessed inside the viewmodel and if you are ready to go against the MVVM principle.

Solution 3: Use of DependencyProperty

Defined problem can also be solved using DependencyProperty i.e. a property that can be set through methods such as, styling, data binding, animation, and inheritance.

Dependency properties are the properties of classes that derive from DependencyObject, and they're special in that rather than simply using a backing field to store their value, they use some helper methods on DependencyObject.

The dependency property is a public static read-only field that must be registered first. After it has been registered, this static property is used to get and set the value in the internal storage system.

Following section explains the steps to solve the problem using DependencyProperty.

Steps to Implement

a. Define the DependencyProperty inside the CustomAttachedProperties class

C#
public static class CustomAttachedProperties
    {
        public static readonly DependencyProperty AttachExProperty =
            DependencyProperty.RegisterAttached(
                "AttachEx",
                typeof(string),
                typeof(CustomAttachedProperties),
                new PropertyMetadata(null, OnAttachExChanged)
                );

        public static void SetAttachEx(DependencyObject d, string attachText)
        {
            d.SetValue(AttachExProperty, attachText);
        }

        public static string GetAttachEx(DependencyObject d)
        {
            return d.GetValue(AttachExProperty) as string;
        }

        private static void OnAttachExChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as FrameworkElement;

            if (control == null)
            {
                return;
            }


            control.DataContextChanged += (sender, args) =>
            {
                //Need to clear AttachProperty value as Caliburn forces the MessageTrigger only when         AttachProperty 
                //has different value then previous one
                control.ClearValue(Message.AttachProperty);
                control.SetValue(Message.AttachProperty, e.NewValue);
            };
        }

    }

In the above given code snippet we have used RegisterAttached to register the property i.e. AttachEx and the PropertyMetaData with its PropertyChangedCallback i.e. OnAttachExChanged implementation reference.

b. Use the dependency property inside the StudentInfoView for its control to define their event.

C#
<Button Name="Conatct" Content="Contact"local:CustomAttachedProperties.AttachEx="[Event Click]=[Action OnContactClick($source,$eventargs)]" Margin="149,108,90,51" />       

Highlighted section shows the way to use the DependencyProperty inside the View i.e. StudentInfoView. Instead of using the Caliburn’s Message.Attach property, DependencyProperty i.e. AttachEx is used subscribe theDataContextChanged event. So whenever there is a change in the PropertyMetadata, it invokes the OnAttachExChanged(). This method internally handles the DataContextChanged event, where it cleans up the Control’s Message.AttachProperty and sets the new value.

Conclusion

A DependencyProperty is set to enable declarative code to alter the properties of an object which reduces the data requirements by providing a more powerful notification system regarding the change of data in a very specific way. The DependencyProperty is useful when application requires some kind of animation or you need to allow the property to be set in Style setters.

Cons:

  • DependencyProperties are meant to be used by WPF's binding system, which is what ties the UI layer to the Data layer. They should be kept in the UI layer, and not in the data layer (ViewModels).
  • DependencyProperties will be applicable mainly at the VisualElements level so it won't be good idea if we create lot of DPs for each of our business requirements. Also there is a greater cost for DP than an INotifyPropertyChanged.

Solution 4: Using Caliburn’s View.Model property

This solution is related to Caliburn’s property only and most of us who just started dealing with C# and various framework available for MVVM implementation won’t be aware of this.

View.Model property of Caliburn is the finding for me. After going through all the approaches I came to know about this property.

In more related to the WPF language View.Model is the DependencyProperty provided by Caliburn.Micro. This provide us a way to host content inside a ContentControl, bind it to model provided by View.Model and update the view based on the selected model

Steps to Implement

First thing I would like to mention is this is very simple and one liner change inside the UserControl which controls selection of the viewmodel.

Just update the MainWindowView as given below and highlighted property is the key to fix the issue. J

C#
<nsVi:StudentInfoView Grid.Row="1" cal:View.Model="{Binding Student}" Background="DarkGray"/>

or

C#
<ContentControl Grid.Row="1" cal:View.Model="{Binding Student}" Background="DarkGray"/>

View.Model

This property binds the view to the specified model. As in this example view or ContentControl is binded to the "Student” i.e. current datacontext. Where it’s not only taking care of change in DataContext but also considers the updates in child view’s Message.Attach property.

As Message.Attach property is similar to define the delegate for some events, and view.model takes care of delegates as well by attaching the view to the current datacontext or telling view that this is the viewmodel/datalayer for data as well as for Event handling.

So we have discussed the four solution along with their pros and cons, I would like to conclude/summarize the approaches.

Summary/Conclusion

Inside the StudentInfo View’s event handler is defined using Caliburn micro’s Message.Attach property [No binding happens on the use of Message.Attach.]

All this does is set up an EventTrigger on the defined event like click for button with an Action of type Caliburn.Micro.ActionMessage. This happens only once for each view that is created! So when a DataTemplate instance is recycled by the host view, although the DataContext/Content and all relevant bindings are updated (StudentInfoView displays the correct information like Student Name and Number), the ActionMessage associated with this view is never set to target i.e. the new ViewModel.

To overcome this problem I have suggested four solutions among them I would prefer Solution 4, as it solves the problem using Caliburn’s property itself and that too with minimal change. By replacing the DataContext/Content proptery of WPF with Solution 4 our datacontext is now turned into the databound to a DependencyProperty (Caliburn.Micro.View.Model), when the template’s DataContext is changed this DependencyProperty is updated. This causes Caliburn.Micro to instantiate a new View (the View.Model DepedencyProperty change handler calls the ViewLocator, which instantiates a new view if one doesn’t exist), where our ActionMessage is correctly bound.

Though other approaches like use of user defined DependencyProperty, fetching the UI element inside the ViewModel helped to resolve the issue but they have their pros and cons. All these approaches can be implemented for limited number of controls, as number of controls will get increase it will impact the maintenance. Secondly these will be against of MVVM principle.

References

http://maonet.wordpress.com/2010/09/24/nested-viewusercontrol-binding-in-caliburn/

http://blog.martindoms.com/2013/01/15/caliburn-micro-datatemplates-actionmessages-and-virtualized-itemscontrols/

http://msdn.microsoft.com/en-us/library/ms752914(v=vs.110).aspx

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Harman International
India India
I am having experience in C++, Qt. I have started developing .Net application using WPF and MVVM.
Always keen to develop/enhance my skill sets and experience.

Comments and Discussions

 
GeneralMy Vote of 5 Pin
Abhinaw Kumar17-Mar-15 1:31
professionalAbhinaw Kumar17-Mar-15 1:31 
QuestionGood article Pin
Sunil P Sharma9-Jun-14 0:59
Sunil P Sharma9-Jun-14 0:59 
GeneralGreat!!! Pin
Praveen Raghuvanshi26-May-14 19:14
professionalPraveen Raghuvanshi26-May-14 19:14 
GeneralRe: Great!!! Pin
Kaushik_M26-May-14 19:54
Kaushik_M26-May-14 19:54 
QuestionThe attached source does not compile using VS2010. Pin
leiyangge26-May-14 15:26
leiyangge26-May-14 15:26 
AnswerRe: The attached source does not compile using VS2010. Pin
Kaushik_M26-May-14 18:43
Kaushik_M26-May-14 18:43 
QuestionGreat! Pin
Volynsky Alex26-May-14 8:37
professionalVolynsky Alex26-May-14 8:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.