MediaOwl v2 Documentation

Introduction

The last months, after winning the extraordinary CM-Contest, I did nearly 90 % of my development work with Caliburn Micro (Just to show how relief this framework is). In this period of time, CM has grown and (thus) changed considerably. As I have never changed MediaOwl since then, I decided to renew this award-winning Silverlight Application.

My thoughts were, that I wanted to make an (even more) useful application. Thing is: you can hardly do that with a sample application. I had to make a tradeoff, and the result is, that those, who already read the docs and experimented a bit with CM, may find MediaOwl a useful source for further knowledge or ideas. On the other hand, MediaOwl may not be the best sample to start CM & Silverlight from scratch.

I must admit that the current lack of documentation is frustrating. I’m trying to counteract this deficiency, but it may take a while. If you have any questions, please drop me a note in the Discussions or via roland.auer[at]ra-design.at! Every (senseful and answerable) question answered will be published in the docs, so everyone can help the community!

Same procedure for bugs you find, of course!

 

Features

  • Extending the Screen- and Conductor classes including:
    • Custom implementation of a Dialog-Service
    • Custom implementation of a Busy Service
    • Defining (optional) Control Templates
  • Modularity/Dynamically loading XAPs
  • Saving/Retrieving custom settings to Isolated Storage
  • Error handling via the EventAggregator
  • Nice UI with a customized JetPack-Theme

 

The Solution

MediaOwl  -  The heart of the application. This project is the frame of the application, loading all modules and displaying them;

MediaOwl.Web  -  The Asp.Net-Web Project, storing all XAP-Modules and passing the list of modules to the MediaOwl-Application;

MediaOwl.Common  -  All modules share this common project. It contains classes, that all modules and the application itself need. The “magic” happens there!

MediaOwl.LastFm  -  A project using the LastFm-REST-Service. This project is a module of MediaOwl;

MediaOwl.Netflix  -  A project using the Netflix OData-Service. This project is a module of MediaOwl;

MediaOwl.WebSearch  -  A project using the Bing V2 SOAP-Service and the Microsoft Translation SOAP Service. This project is a module of MediaOwl;

MediaOwl.Cryptos  -  A project showing the basic types of encryption. It has nothing to do with media search, I just wanted to implement a module, that does not connect to a web service. This project is a module of MediaOwl;

 

Eyes-on: Features

The following paragraphs are discussing some of the important features of MediaOwl/Caliburn.Micro. At the beginning of each feature is a grey list of Namespaces and/or Class-Names implementing the mentioned feature. Be sure to take a look at them!


Custom Screens and Conductors

  • MediaOwl.Common.ScreenManagement

I wanted to extend the usage of the CM-Screens and Conductors, in detail capability for dialogs, busy-states and an action, that fires when the view is loaded for the first time. These requirements have to be implemented double track, one time inherited from Screen (ExtendedScreen), and one time inherited from Conductor<T>.Collection.OneActive (ExtendedConductor<T>).

Additionally, I wanted to implement some specific properties, that are an assemble of the “Extended”-Screens and Conductors. For this purpose, I invented a Workspace (inheriting from ExtendedConductor<T>), and a Workitem<TParentWorkspace> (inheriting from ExtendedScreen).

Overview of the Interfaces:

Interface Overview

The according classes:

Classes

 

Navigate between Screens

  • MediaOwl.Common – Show
  • MediaOwl.Common.ScreenManagemen – OpenChildResult

Navigation between Screens can easily be done with the coroutine OpenChildResult. This couroutine can be called with the method Show.Child<TChild>().In<TParent>().Configured(x => …) or any of its overloads.

 

The Dialog Service

  • MediaOwl.Common.Dialog
  • MediaOwl.Common.ControlTemplates – DialogControl & DialogIndicator
  • MediaOwl.Common – Show
  • MediaOwl.Common.ViewModels – DialogMessageViewModel
  • MediaOwl.Common.Views – DialogMessageView

The target was to create a modal dialog service, which has the following abilities:

  • The dialog can be shown local in every screen, not influencing other screens.
  • A dialog can be sent from one screen to another.
  • The dialog service is asynchronous, and should be handled with an IResult
  • The shown dialog is following the MVVM-pattern.

To meet the requirements, I implemented the interface IDialogCapable, which gives a screen the capability to take many instances of IDialog. If an IDialogCapable has no active dialog, but has dialogs in the DialogConductor, the first IDialog is taken and made the ActiveDialog. As the IDialog is an IScreen, it can call TryClose() and be removed from the DialogConductor. If the DialogConductor has any more dialogs, everything starts from the beginning.

The IDialogCapable is ideally implemented via the DialogIndicator. The DialogIndicator is – like the well-known BusyIndicator for its Busy-Dialog – a Container for showing dialogs. Simply insert <ctrl:DialogIndicator cal:View.Model="{Binding ActiveDialog}" /> in your View’s XAML, and you can show all kinds of dialog in it! Basically, you don’t need the DialogIndicator, every ContentControl cal:View.Model="{Binding ActiveDialog}" can display the dialog, but DialogIndicator adds nice and neat animations.

Info: The DialogIndicator is automatically implemented in the custom controls WorkitemControl and WorkspaceControl!

A dialog itself can be created by implementing IDialog in the ViewModel or – easier – by inheriting from DialogScreen. DialogScreen inherits from Screen and implements IDialog as it should be, and provides just one additional property called DialogMessage, which could be used to display the dialog’s message. The View of the dialog has an optional predefined wrapper-control as well, the DialogControl. Just place it in the View as the root-control!

Info: As most of the dialogs shown in an application are simple messages, I created one implementation of IDialog myself – a Message-Box-Dialog (DialogMessageViewModel & DialogMessageView).

To show a dialog in a screen, you must return an instance of the IResult ShowDialog in a ViewModel’s method, or –easier – call the static method Show.Dialog<TDialog>.In<TParent>.Configured(x => …).

 

The Busy Service

  • MediaOwl.Common.Busy
  • MediaOwl.Common.ControlTemplates – DialogControl & DialogIndicator
  • MediaOwl.Common – Show
  • MediaOwl.Common.ViewModels – DialogBusyViewModel
  • MediaOwl.Common.Views – DialogBusyView

The target was to create a Busy Service, which can be influenced in the ViewModel (also by other ViewModels). This was very easy to achieve, as the dialog service already provides this feature. Thus, the Busy-Service is implemented quite like the Dialog-Service, except for the fact that there is always only one Busy-Screen.

The View of the Busy-Service is a DialogControl of the DialogService, and the wrapper in the parent is a DialogIndicator, which is bound to cal:View.Model="{Binding CurrentBusyViewModel}".

Info: The DialogIndicator of the Busy-Service is automatically implemented in the custom controls WorkitemControl and WorkspaceControl!

 

Custom Controls

  • MediaOwl.Common.ControlTemplates – WorkitemControl & WorkspaceControl

The two controls WorkitemControl and WorkspaceControl are exactly the same. I created them, because it is easier to implement a common look and feel in an application. They only implement Dependency Properties for the Busy- and Dialog Service. 

 

Modularity

  • MediaOwl.Core.Modularity
  • MediaOwl.ViewModels – ModuleViewModel
  • MediaOwl.Views – ModuleView
  • MediaOwl.Web – index.aspx & index.php

[I am working on that]

 

Isolated Storage

  • MediaOwl.Common.IsolatedStorage
  • MediaOwl.ViewModels – ModuleViewModel
  • MediaOwl.Views – ModuleView

[I am working on that]

 

Error Handling

  • MediaOwl.Common.Messages – ErrorMessage
  • MediaOwl.ViewModels – MainViewModel

[I am working on that]

 

Other Useful Gimmicks

MediaOwl.Common.Converters – Visibility

 ConverterThis converter converts a Boolean value to a visibility value. It also converts any object to a visibility, by checking if it is null or not. The value can be inverted as well.

MediaOwl.Common.Logging – DebugLog

A debugger for CM writing all information to the Visual Studio Debug-Output-Window. Can be implemented by writing LogManager.GetLog = type => new DebugLog(type); into the Bootstrapper’s constructor.

MediaOwl.Common – Run

A simple shortcut for CM’s Coroutine.BeginExecute, taking single IResults or an IEnumerable<IResult>.

MediaOwl.Common.Converters – StopWatch

An IResult that “delays” a coroutine execution.

MediaOwl.Common.Converters – ViewHelper

A class that helps you to show an animation in the view or scroll a ScrollViewer/ListBox to a certain position.

MediaOwl.Common.Converters – WebClientDownload

An IResult for a WebClient download, returns a stream or a string.

 

FAQ

What's the application for?

As written above, you can search for several topics in the web, music and movies. In the web-part, you can search for several typical search-engine-topics, in the music-part you can search for artists, albums, tracks or you sort them out by using the top tags. In the movies-part you can search for titles, which means movies and series, people, which means actors and directors, or a genre. Finally, there is a encryption-part, which shows the basic types of encryption.

 

Where's the data from?

The general search is powered by the Bing v2 API, the music search is powered by Last.fm, getting the data from their REST-service. The movie search is powered by Netflix, where its OData-Service is used.

 

What about the source?

The code is under MIT-License. I have to point out, that if you'd like to build the application, you have to fill in a (better your personal) Last.fm-Api-Key first! The key is stored in LastFmDataAccess.resx.

 

What is needed to use the Event Aggregator?

In general [in the MediaOwl-case]:

  1. A class that represents the message [ErrorMessage]
  2. A class that publishes the message [e.g. LoadData], means: get the EventAggregator (from DI-container) and call eventAggregator.Publish(message) [eventAggregator.Publish(errorMessageInstance)];
  3. A class that subscribes to the message [e.g. ShellViewModel], means: implement IHandle<T> [IHandle<ErrorMessage>] in the Subscriber-Class [ShellViewModel], get the EventAggregator (from DI-container), call eventAggregator.Subscribe(Subscriber-Class) [eventAggregator.Subscribe(this)];
  4. Implement "that-what-has-to-be-done" in the Handle-Method of IHandle<T>.

 

Bootstrap-Bill's Bootstrapper?

You need to bootstrap your application. You can look at the AppBootstrapper, but that is taken from the Docs/Recipes of CM. Better take a look over there.

 

I want a Logger! But how?

Enable logging by creating a class that implements ILog (e.g. DebugLog taken from marcoamendola's GameLibrary-Sample), then enable logging the same way as it is done in the MediaOwl-Bootstrapper.

 

Why is the application called MediaOwl?

Media: Because it's a media-search-ui.

Owl: There is a reason indeed... I'm quite curious, if somebody finds out. (Just a hint: It has something to do with Caliburn Micro)

Last edited Jul 14, 2011 at 2:03 PM by RAuer, version 8

Comments

No comments yet.