开发者

Reusing Views and Viewmodel with MEF & Silverlight

开发者 https://www.devze.com 2023-02-12 04:39 出处:网络
Here is what I\'d like to do : I have an Silverlight application using navigation frame and MEF. (like this one : http://msdn.microsoft.com/en-us/magazine/gg535672.aspx)

Here is what I'd like to do :

I have an Silverlight application using navigation frame and MEF. (like this one : http://msdn.microsoft.com/en-us/magazine/gg535672.aspx) This application consists of a set of buttons. Each button click load a view and its associated ViewModel.

Within theses views, I've a list with items and when I click on each items it refreshs a kind of sub-view in this view.

I'd like to create a navigation system : for example myapp.aspx#view1/2, where 2 is in fact the item clicked in the list. If I click on one of the button, it would load a default item and refresh all the view, but when I click on an item, I wouldn't like to refresh all the view but only certain part of the view (I do not want to create another instance of the view and viewmodel).

My problem is in fact that I would like to get the best pratice to get a reference to an existing view or viewmodel when i'm navigating to this page that has already been loaded (for example from myapp.aspx#view1/2 to myapp.aspx#view1/3)(I plan to do this in开发者_开发知识库to the BeginLoad of the ContentLoader class) If I get the viewmodel, I can do that I want by changing for example the current itemId property which could refresh the view thanks to binding.

Thanks in davance if you have something to propose.


A common approach is to use some form of Messenger to do this type of operation. The item's click could trigger the sending of a message, with the Item attached. The ViewModel in question would be a subscriber, and edit its current settings (ie: it's ItemId, which would trigger the binding refresh).

The most common implementations are usually ones similar to the Messenger service in MVVM Light.

It's fairly easy to roll your own here, though, especially since you're already using MEF. Just create a service to handle the message passing, and import it into both endpoints.


Actually, I would have prefered to use an URI to navigate in my application when I click on an item, but if I use an URI, the entire view is reloading and not the specific part I'd like to.

With the messenger, I won't be able to use navigation with url within the view, I think ? Or else I didn't really figure out what you proposed to me.

The algorithm I would like to take is :

  • navigate("...asp#MyView1/1")
    • MyView1 is current view ?
      • yes then I'd like to get the viewmodel of the current view and change it the ItemId property with 1
      • no, then the view will be created

And I'd like to implement this algorithm there : (this is the place where the view is instancied for each navigation, in my CompositionNavigationContentLoader class)

   public IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState)
    {
        // Convert to a dummy relative Uri so we can access the host.
        var relativeUri = new Uri("http://" + targetUri.OriginalString, UriKind.Absolute);

        // Get the factory for the ViewModel.
        var viewModelMapping = ViewModelExports.FirstOrDefault(o => o.Metadata.Key.Equals(relativeUri.Host, StringComparison.OrdinalIgnoreCase));
        if (viewModelMapping == null)
            throw new InvalidOperationException(
                String.Format("Unable to navigate to: {0}. Could not locate the ViewModel.", targetUri.OriginalString));

        // Get the factory for the View.
        var viewMapping = ViewExports.FirstOrDefault(o => o.Metadata.ViewModelContract == viewModelMapping.Metadata.ViewModelContract);
        if (viewMapping == null)
            throw new InvalidOperationException(
                String.Format("Unable to navigate to: {0}. Could not locate the View.", targetUri.OriginalString));

        // Resolve both the View and the ViewModel.
        var viewFactory = viewMapping.CreateExport();
        var view = viewFactory.Value as Control;
        var viewModelFactory = viewModelMapping.CreateExport();
        var viewModel = viewModelFactory.Value as IViewModel;

        // Attach ViewModel to View.
        view.DataContext = viewModel;
        viewModel.OnLoaded();

Thanks.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号