Attention: We are retiring the ASP.NET Community Blogs. Learn more >

How the Presentation Model could look like when using Silverlight 2.0 (Part 5)

Maybe the title of my blog post are not the best one now when I write about my little Presentation Model framework for Silverlight.

To day I notice some problems when it comes to switching views and also play movies and animations etc. For example to start playing a movie we need to call the MediaElement’s Play method. With my Framework we can only execute a Action method located in our Presentation Model, and I don’t want to pass a FrameworkElement as an argument to the Presentation Model, so there was no way to make sure an Action method can start playing a movie. So to solve this I created a specific class with the name ActionResult, this ActionResult class:

public class ActionResult
{
    public ActionResult()
    {
       this.ActionResultHandler = new DefaultActionResultHandler();
    }

    public IActionResultHandler ActionResultHandler { get; protected set; }
}


Action methods can then return a ActionResult:

public class CustomerPresentationModel : Silverlight.Extension.PresentationModel
{
       public ActionResult Show(string customerId)
       {
           return ChangeView("About.About", base.PreviousUsetState);
       }

       public ActionResult PlayMovie()
       {
           return new MovieActionResult(null, MovieAction.Play);
       }
}


If an ActionResult is returned from a Action method, I will use the ActionResult’s ActionResultHandler and invoke the HandleActionResult method, where I pass the FrameworkElement that trigged the Action method and also pass the ActionResult class as an argument:

public interface IActionResultHandler
{
    bool HandleActionResult(FrameworkElement sourceElement, ActionResult returnValue);
}


To make sure I can start playing a movie from the Action method, I will pass a MovieActionResult, which will use a MoveActionResultHandler to handle the ActionResult and start playing the movie:

public class MovieActionResult : ActionResult
{
     public MovieActionResult(Stream mediaSource, MovieAction movieAction)
     {
        this.MovieAction = movieAction;
        this.MediaSource = mediaSource;
        base.ActionResultHandler = new MovieActionResultHandler();
     }

     public MovieAction MovieAction { get; internal set; }

     public Stream MediaSource { get; internal set; }
}

 

public class MovieActionResultHandler : IActionResultHandler
{
    public bool HandleActionResult(FrameworkElement sourceElement, ActionResult returnValue)
    {
        var mediaElement = sourceElement as MediaElement;

        if (mediaElement == null)
           throw new Exception(string.Format("The sourceElement ({0},{1}) for the MovieActionResultHandler is not of type MediaElement", sourceElement.Name, sourceElement.GetType().Name));

        var actionResult = returnValue as MovieActionResult;

        if (actionResult == null)
           throw new Exception("The returnValue agrument is not of type MovieActionResult");

        switch (actionResult.MovieAction)
        {
            case MovieAction.Play:
                 mediaElement.Play();
                 break;
            case MovieAction.Pause:
                 mediaElement.Pause();
                 break;
            case MovieAction.Resume:
                 mediaElement.Play();
                 break;
            case MovieAction.Stop:
                 mediaElement.Stop();
                 break;
            default:
                throw new Exception("Can't handle MovieAction");
        }
        return true;
    }
}


The MovieResultHandler can now interact with the FrameworkElement that trigged the Action method.

So to play a movie when the MouseLeftButtonUp is trigged we can simply write:

<MediaElement e:Attach.MouseLeftButtonUp="PlayMovie" AutoPlay="False" Source="http://localhost:4317/movie.wmv" Height="200" Width="200"/>

I have also added a ActionResult called DynamicChangeViewActionResult and a handler for it. By using this ActionResult we can dynamically specify a View and make sure our Silverlight applicaiton switches view after an Action method is executed:

public ActionResult Show(string customerId)
{
    return ChangeView("About", customerId);
}


The ChangeView is a method added to the base class PresentationModel which can be used to get some helper method, but aren’t needed. The ChangeView will return a DynamicChangeViewActionResult, and will get the About.xaml page and automatically replace the content of the “LayoutRoot” element with the new View. So my Framework can sort of also use the MVC pattern. By passing object as a second argument to the ChangeView, we can pass additional information to the next View’s Presentation Model’s Action methods. We can also specify a name of a ContentControl or Panel located on our View, and the make sure only a part of the View is updated with a new UserControl instead of the whole view.

public ActionResult Show(string customerId)
{
   return ChangeView("About", "MyPanelToUpdate", customerId);
}


So the basic ideas of using the ActionResult feature is only to make sure others can return their own ActionResult and handle the result of the Action method, for example to play an animation, or change an image or what ever.

4 Comments


  • @Jonas:
    Nice! The reason I want to avoid using the Supervising Controller pattern, is to make the Presentaion Model clean and try to avoid passing the View to the "presenter/controller". Maybe I will add that suppport to also make it possible to use the Framework with the MVP (sorry, Supervising Controller pattern) ;) In that case I can use the framework for both, MVC, "MVP" and Presentation Model pattern. But the framework is only a something I do for fun, so I will probably not add it to Codeplex, there are already so many other frameworks out there.

  • Would you tell us your recommendation on the patterns already existing, I mean Prism, Caliburn, etc... or release your own completed for others to use in their SL development projects?

    I like the way you think on this topic, and I would like to choose an all-in-one solution (if it exists) for any Silverlight LOB application development. To choose an only one is a way to make a development team work consistently, to do their job routinish.

    Could you help me to think it over? Thank you man for your tutorial serie!


  • @Gabor:
    My "project" are only to see how "simple" or "hard" it should be to create such kind of framework. My suggestion is that you take a look at Prism, Caliburn and Silverlight.FX, and use the one you like the most.

  • An additional note, that it is fun to understand patterns, fun to follow your articles growing from a basic idea to a "framework". Personally, I'm going to utilize your articles in understanding the usage of the most applicable patterns in a SL development.

    Anyway, I wouldn't reimplement its fundamental code but would be an advanced user of one of the existing frameworks. To know its limits, to use its advantages, and to extend its functionality, but I have to choose the right way. Without deep experiences it's hard to choose. There are some mentioned obstacle in others notes (e.g. assigning custom actions), and a framework should not contain any critical "obstacle", and should leave space for custom or maybe application-dependent features (all this meaned "extensibility"). Waiting for your notes ;)

    You really did a great job to make your reader conscious in applying patterns, so thank you again.

Comments have been disabled for this content.