Child ViewModel Null When Using [Import]

Topics: Bootstrappers & IoC
May 22, 2013 at 7:56 PM
Hi,

I am trying hard to get up to speed on MEF, and I have run into an issue.

Let's say I have a parent View Model that will have a child ViewModel as a property, and needs to wire up to PropertyChanged on the child.

So, I have something like this....
    [Export(typeof (ParentViewModel))]
    public class ParentViewModel : Screen
    {
        [ImportingConstructor]
        public ParentViewModel()
        {
            // **********************************
            // PROBLEM IS, THIS IS NULL RIGHT NOW 
            // **********************************
            ChildProperty.PropertyChanged +=
                (sender, args) =>
                    {
                        // do something here
                    };
        }

        [Import]
        public ChildViewModel ChildProperty { get; set; }

        protected override void OnActivate()
        {
            // **********************************************************************************
            // CHILD PROPERTY IS NOT NULL HERE, BUT I'd RATHER NOT USE THIS BECAUSE
            // A) I WON'T ALWAYS INHERIT SCREEN
            // B) THIS COULD BE USED AS A PROPERTY WITHOUT A VIEW WHERE ACTIVATE WON'T GET CALLED
            // **********************************************************************************
            ChildProperty.PropertyChanged +=
                (sender, args) =>
                {
                    // do something here
                };
          
            base.OnActivate();
        }
    }

    [Export(typeof(ParentViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class ChildViewModel : PropertyChangedBase
    {
        private bool _myProperty;

        [ImportingConstructor]
        public ChildViewModel()
        {
        }

        public bool MyProperty
        {
            get { return _myProperty; }
            set
            {
                if (_myProperty == value)
                    return;

                _myProperty = value;
                NotifyOfPropertyChange(() => MyProperty);
            }
        }
    }
In this example, the Child View Model property of the parent is still null when I try to attach to the PropertyChanged event in the Parent's constructor. If I override Activate() and attach to the event there, that works fine. However, I don't always want to have to rely on Activate() for various reasons (like maybe I'll use an instance of a view model within a view model and not create a view for it).

Given this, what is the best way to know when the [Import] properties have been created in my parent view model so I can set properties, attach to events, etc on them? Should I just not use [Import] and manually create the child view models (though I would like to embrace MEF)?

Thanks!
Scott
May 22, 2013 at 11:07 PM
Edited May 22, 2013 at 11:08 PM
You can use [OnImportSatisfied] on a method and it will identify it to MEF as a callback when all imports have been resolved.
[OnImportSatisfied]
public void Initialize()
{
     ChildProperty.PropertyChanged +=
                (sender, args) =>
                    {
                        // do something here
                    };
}