views:

581

answers:

4

Hi,

I have been looking around and haven't found much information on this yet. I have a PRISM project set up and it all seems to be working so far, within the main class of a module I am programatically creating my views.

What I am trying to do is get an object sent through to the viewmodel for each instance of the view. At the moment I am trying to pass the object into the views constructor and do something like this:

   public MyView(IUnityContainer container, List<string> myDataObject)
    {
        InitializeComponent();

        MyViewViewModel vm = LayoutRoot.DataContext as MyViewViewModel;
        vm.DataObject = myDataObject;
    }

This causes a NullReferenceObject for vm.DataObject, I assume the viewmodel hasn't been properly instantiated at this point.

Can anyone guide me on how this should be done? should the data object even be send via the view?

Thanks for your time

A: 

Since you are using a Unity container, you could use it to pass the DataContext object through views. Use RegisterInstance when you create the DataContext, then use Resolve on each appropriate view. If you have more than one DataContext, use named registration.

Konamiman
Hi, thanks for your reply,I see what you mean about the container, but each instance is of the same view and will be receiving the same object type passed in, so how would named registration work? as the view wouldn't know which context it would need to resolve.Also, how does resolving the datacontext in the view make it available to the viewmodel?Thanks again
A: 

Is there a way to manually create the view and it's view model and set the relevant data objects on the viewmodel so that they can be data bound, then tie both together before adding to a region?

+1  A: 

In our code, and in all the videos that I've watched, you set it up so that the view takes, as a parameter, the ViewModel.

    public ThisView(ThisVM vm)
    {
        InitializeComponent();
        DataContext = vm;
    }

If you need to pass things around from somewhere else, you can use the eventAggregator to subscribe and publish to them.
Kind of like this in the spot where you have the DataObject:

    _EventAggregator.GetEvent<PushModelEvent>().Subscribe(ReceiveModel, true);

And like this where you want to have access to it (probably the VM):

    _EventAggregator.GetEvent<PushModelEvent>().Publish(_Model);

There are still some synchronous things to deal with, but, if this is what you want, this should get you going.

thepaulpage
A: 

In a sample app I wrote I created an interface which was implemented by the view. This interface has 1 member, SetViewModel. This method takes an object, which is the ViewModel. The ViewModel provides the View with places to bind to and handles commands.

public interface IDemoView
{
    void SetViewModel(object viewModel);
}

the implementation of this interface in the actual view looks like this:

public partial class DemoView : UserControl, IDemoView
{
    public DemoView()
    {
        InitializeComponent();
    }

    public void SetViewModel(object viewModel)
    {
        DataContext = viewModel;
    }
}

The constructor of the View remains default, and the only code that will ever be in the codebehind is this SetViewModel method.

In the constructor of the ViewModel class, it calls this method and passes itself to the view.

public IDemoView View { get; private set; }
private IDemoModel _model;
public DemoViewModel( IDemoView view, IDemoModel model)
{            
    _model = model;            
    View = view;
    View.SetViewModel(this);
}

The initialize method in the Module class registers the types with the UnityContainer and adds the view to the region

public void Initialize()
{
    _container.RegisterType<IDemoView, DemoView>();
    _container.RegisterType<IDemoModel, DemoModel>();
    _container.RegisterType<IDemoViewModel, DemoViewModel>();

    var viewModel = _container.Resolve<IDemoViewModel>();

    _regionManager.Regions["MainRegion"].Add(viewModel.View);
}
Sorskoot