Adding Catel mvvm behavior through code

Nov 2, 2011 at 3:33 PM

Hi,

A) Due to a known issue in SL4 (see discussion 275318), I am adding the Catel mvvm behavior through code. I just want to check whether or not I am following the correct procedure (if not, please comment).

B) This causes my ViewModel to be autotically created (when the view is created). The ViewModel property is readonly. Is there also a way of manually creating a ViewModel and passing it to the ctor of my usercontrol?

Procedure:

1) I add a "User Control (Silverlight with Catel, logic in behavior" to my project (in my "Views" folder)

2) I comment out this part in the xaml, and add 4 lines of code in the code behind file of my usercontrol:

<!--i:Interaction.Behaviors>
        <catel:UserControlBehavior x:Name="mvvmBehavior" ViewModelType="ViewModels:SubmitRegistrationRequestViewModel" />
    </i:Interaction.Behaviors-->
 
    public partial class SubmitRegistrationRequestViewBehavior : UserControl, IViewModelContainer
    {

        private Catel.Windows.Controls.MVVMProviders.UserControlBehavior mvvmBehavior;
        /// <summary>
        /// Initializes a new instance of the <see cref="SubmitRegistrationRequestViewBehavior"/> class.
        /// </summary>
        public SubmitRegistrationRequestViewBehavior()
        {
            InitializeComponent();

            mvvmBehavior = new Catel.Windows.Controls.MVVMProviders.UserControlBehavior();
            mvvmBehavior.ViewModelType = typeof(ViewModels.SubmitRegistrationRequestViewModel);
            System.Windows.Interactivity.Interaction.GetBehaviors(this).Add(mvvmBehavior);

            mvvmBehavior.ViewModelChanged += (sender, e) =>
                                                 {
                                                     if (ViewModelChanged != null)
                                                     {
                                                         ViewModelChanged(this, e);
                                                     }
                                                 };
        }

        /// <summary>
        /// Gets the view model that is contained by the container.
        /// </summary>
        /// <value>The view model.</value>
        public IViewModel ViewModel
        {
            get { return mvvmBehavior.ViewModel; }
        }

        /// <summary>
        /// Occurs when the <see cref="ViewModel"/> property has changed.
        /// </summary>
        public event EventHandler<EventArgs> ViewModelChanged;
    }
}

 


Nov 2, 2011 at 4:59 PM

You are doing it the right way. The view model is only automatically created when the control is loaded (not when it is created). You can confirm this by creating the SubmitRegistrationRequestViewBehavior control in code and not adding it to a visual tree. I have no access to the SubmitRegistrationRequestViewModel, but it will be created only if:

  1. The DataContext of the control can be injected into a constructor of the view model
  2. The view model has an empty constructor

You can set the DataContext of the control to a view model, and this way "inject" a view model into a control instead of letting it be created first. In fact, the user control first checks whether the DataContext is already a valid VM for the user control. If so, it keeps it that way.

I hope this additional info helps you solve the issue.

Nov 2, 2011 at 5:23 PM

OK, thanks for the explanation. It is nice to see that the ViewModel can sneak in through the back door (the DataContext) and that the view is not surprised to find it there :-)

Already tried it and it works just fine (of course). This could be something to add to the Catel help ("How to add Catel behaviors programatically").

Nov 2, 2011 at 6:20 PM

Thanks for the tip, just added 2 new questions to the FAQ of the documentation. Currently re-uploading it.