protected override void Prepare()
    {
      base.Prepare();

      _defaultScreen = new LocalMediaNavigationScreenData(_genericPlayableItemCreatorDelegate);

      // Dynamic screens remain null - browse media states don't provide dynamic filters
      _availableScreens = null;

      _defaultSorting = new BrowseDefaultSorting();
      _availableSortings = new List<Sorting.Sorting>
        {
          _defaultSorting,
          new SortByTitle(),
          new SortByDate(),
          // We could offer sortings here which are specific for one media item type but which will cope with all three item types (and sort items of the three types in a defined order)
        };

      var optionalMias = new[]
      {
        AudioAspect.ASPECT_ID,
        VideoAspect.ASPECT_ID,
        ImageAspect.ASPECT_ID
      }.Union(MediaNavigationModel.GetMediaSkinOptionalMIATypes(MediaNavigationMode));

      _customRootViewSpecification = new AddedRemovableMediaViewSpecificationFacade(
        new LocalMediaRootProxyViewSpecification(_viewName, _necessaryMias, optionalMias));
    }
    /// <summary>
    /// Returns context variables to be set for the given workflow state id.
    /// </summary>
    /// <param name="workflowStateId">Workflow state which determines the root media navigation state.</param>
    /// <returns>Mapping of context variable keys to values.</returns>
    protected static IDictionary<string, object> PrepareRootState(Guid workflowStateId)
    {
      IDictionary<string, object> result = new Dictionary<string, object>();
      // The initial state ID determines the media model "part" to initialize: Browse local media, browse media library, audio, videos or images.
      // The media model part determines the media navigation mode and the view contents to be set.
      NavigationData navigationData;
      MediaNavigationMode mode;
      if (workflowStateId == Consts.WF_STATE_ID_AUDIO_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Audio;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new AudioItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_AUDIO_VIEW_NAME,
            null, Consts.NECESSARY_AUDIO_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterByAlbum = new AudioFilterByAlbumScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new AudioShowItemsScreenData(picd),
              new AudioFilterByArtistScreenData(),
              filterByAlbum, // C# doesn't like it to have an assignment inside a collection initializer
              new AudioFilterByGenreScreenData(),
              new AudioFilterByDecadeScreenData(),
              new AudioFilterBySystemScreenData(),
              new AudioSimpleSearchScreenData(picd),
            };
        Sorting.Sorting sortByAlbumTrack = new AudioSortByAlbumTrack();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              sortByAlbumTrack,
              new SortByTitle(),
              new AudioSortByFirstGenre(),
              new AudioSortByFirstArtist(),
              new AudioSortByAlbum(),
              new AudioSortByTrack(),
              new SortByYear(),
              new SortBySystem(),
          };
        navigationData = new NavigationData(null, Consts.RES_AUDIO_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterByAlbum, availableScreens, sortByAlbumTrack)
          {
              AvailableSortings = availableSortings
          };
      }
      else if (workflowStateId == Consts.WF_STATE_ID_VIDEOS_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Videos;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new VideoItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_VIDEOS_VIEW_NAME,
            null, Consts.NECESSARY_VIDEO_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterByGenre = new VideosFilterByGenreScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new VideosShowItemsScreenData(picd),
              new VideosFilterByLanguageScreenData(),
              new VideosFilterByActorScreenData(),
              filterByGenre, // C# doesn't like it to have an assignment inside a collection initializer
              new VideosFilterByYearScreenData(),
              new VideosFilterBySystemScreenData(),
              new VideosSimpleSearchScreenData(picd),
          };
        Sorting.Sorting sortByTitle = new SortByTitle();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              sortByTitle,
              new SortByYear(),
              new VideoSortByFirstGenre(),
              new VideoSortByDuration(),
              new VideoSortByDirector(),
              new VideoSortByFirstActor(),
              new VideoSortBySize(),
              new VideoSortByAspectRatio(),
              new SortBySystem(),
          };
        navigationData = new NavigationData(null, Consts.RES_VIDEOS_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterByGenre, availableScreens, sortByTitle)
          {
              AvailableSortings = availableSortings
          };
      } 
      else if (workflowStateId == Consts.WF_STATE_ID_SERIES_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Videos;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new SeriesItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_SERIES_VIEW_NAME,
            null, Consts.NECESSARY_SERIES_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterBySeries = new SeriesFilterByNameScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new SeriesShowItemsScreenData(picd),
              filterBySeries, // C# doesn't like it to have an assignment inside a collection initializer
              new VideosFilterByLanguageScreenData(),
              new SeriesFilterBySeasonScreenData(),
              new VideosFilterByGenreScreenData(),
              new VideosSimpleSearchScreenData(picd),
          };
        Sorting.Sorting sortByEpisode = new SeriesSortByEpisode();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              sortByEpisode,
              new SortByTitle(),
              new SortByDate(),
              new SortBySystem(),
          };
        navigationData = new NavigationData(null, Consts.RES_SERIES_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterBySeries, availableScreens, sortByEpisode)
          {
              AvailableSortings = availableSortings
          };
      }
      else if (workflowStateId == Consts.WF_STATE_ID_MOVIES_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Movies;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new MovieItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_MOVIES_VIEW_NAME,
            null, Consts.NECESSARY_MOVIES_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterByGenre = new VideosFilterByGenreScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new MoviesShowItemsScreenData(picd),
              new VideosFilterByActorScreenData(),
              filterByGenre, // C# doesn't like it to have an assignment inside a collection initializer
              new VideosFilterByYearScreenData(),
              new VideosFilterBySystemScreenData(),
              new VideosSimpleSearchScreenData(picd),
          };
        Sorting.Sorting sortByTitle = new SortByTitle();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              sortByTitle,
              new SortByYear(),
              new VideoSortByFirstGenre(),
              new VideoSortByDuration(),
              new VideoSortByDirector(),
              new VideoSortByFirstActor(),
              new VideoSortBySize(),
              new VideoSortByAspectRatio(),
              new SortBySystem(),
          };

        navigationData = new NavigationData(null, Consts.RES_MOVIES_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterByGenre, availableScreens, sortByTitle)
          {
              AvailableSortings = availableSortings
          };
      }
      else if (workflowStateId == Consts.WF_STATE_ID_IMAGES_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Images;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new ImageItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_IMAGES_VIEW_NAME,
            null, Consts.NECESSARY_IMAGE_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterByYear = new ImagesFilterByYearScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new ImagesShowItemsScreenData(picd),
              filterByYear, // C# doesn't like it to have an assignment inside a collection initializer
              new ImagesFilterBySizeScreenData(),
              new ImagesFilterBySystemScreenData(),
              new ImagesSimpleSearchScreenData(picd),
          };
        Sorting.Sorting sortByYear = new SortByYear();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              new SortByYear(),
              new SortByTitle(),
              new ImageSortBySize(),
              new SortBySystem(),
          };
        navigationData = new NavigationData(null, Consts.RES_IMAGES_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterByYear, availableScreens, sortByYear)
          {
              AvailableSortings = availableSortings
          };
      }
      else
      {
        // If we were called with a supported root state, we should be either in state WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT
        // or WF_STATE_ID_MEDIA_BROWSE_NAVIGATION_ROOT here
        if (workflowStateId != Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT &&
            workflowStateId != Consts.WF_STATE_ID_BROWSE_MEDIA_NAVIGATION_ROOT)
        {
          // Error case: We cannot handle the given state
          ServiceRegistration.Get<ILogger>().Warn("MediaNavigationModel: Unknown root workflow state with ID '{0}', initializing local media navigation", workflowStateId);
          // We simply use the local media mode as fallback for this case, so we go on
          workflowStateId = Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT;
        }
        mode = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? MediaNavigationMode.BrowseLocalMedia :
            MediaNavigationMode.BrowseMediaLibrary;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi =>
          {
            if (mi.Aspects.ContainsKey(AudioAspect.ASPECT_ID))
              return new AudioItem(mi)
                {
                    Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
                };
            if (mi.Aspects.ContainsKey(VideoAspect.ASPECT_ID))
              return new VideoItem(mi)
                {
                    Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
                };
            if (mi.Aspects.ContainsKey(ImageAspect.ASPECT_ID))
              return new ImageItem(mi)
                {
                    Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
                };
            return null;
          };
        IEnumerable<Guid> necessaryMIATypeIDs = new Guid[]
            {
                ProviderResourceAspect.ASPECT_ID,
                MediaAspect.ASPECT_ID,
            };
        IEnumerable<Guid> optionalMIATypeIDs = new Guid[]
            {
                AudioAspect.ASPECT_ID,
                VideoAspect.ASPECT_ID,
                ImageAspect.ASPECT_ID,
            }.Union(skinDependentOptionalMIATypeIDs);
        string viewName = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ?
            Consts.RES_LOCAL_MEDIA_ROOT_VIEW_NAME : Consts.RES_BROWSE_MEDIA_ROOT_VIEW_NAME;
        ViewSpecification rootViewSpecification = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ?
            new AddedRemovableMediaViewSpecificationFacade(new LocalMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)) :
            new AddedRemovableMediaViewSpecificationFacade(new BrowseMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs));
        // Dynamic screens remain null - browse media states don't provide dynamic filters
        AbstractScreenData screenData = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ?
            (AbstractScreenData) new LocalMediaNavigationScreenData(picd) : new BrowseMediaNavigationScreenData(picd);
        Sorting.Sorting browseDefaultSorting = new BrowseDefaultSorting();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              browseDefaultSorting,
              new SortByTitle(),
              new SortByDate(),
              // We could offer sortings here which are specific for one media item type but which will cope with all three item types (and sort items of the three types in a defined order)
          };
        navigationData = new NavigationData(null, viewName, workflowStateId,
            workflowStateId, rootViewSpecification, screenData, null, browseDefaultSorting)
          {
              AvailableSortings = availableSortings
          };
      }
      result.Add(Consts.KEY_NAVIGATION_MODE, mode);
      result.Add(Consts.KEY_NAVIGATION_DATA, navigationData);
      return result;
    }
 /// <summary>
 /// Returns context variables to be set for the given workflow state id.
 /// </summary>
 /// <param name="workflowStateId">Workflow state which determines the root media navigation state.</param>
 /// <returns>Mapping of context variable keys to values.</returns>
 protected static IDictionary<string, object> PrepareRootState(Guid workflowStateId)
 {
   IDictionary<string, object> result = new Dictionary<string, object>();
   // The initial state ID determines the media model "part" to initialize: Browse local media, browse media library, audio, videos or images.
   // The media model part determines the media navigation mode and the view contents to be set.
   NavigationData navigationData;
   string mode;
   if (_initializers.ContainsKey(workflowStateId))
   {
     // Use the IMediaNavigationInitializer that is associated with our root workflow state.
     IMediaNavigationInitializer initializer = _initializers[workflowStateId];
     initializer.InitMediaNavigation(out mode, out navigationData);
   }
   else
   {
     // If we were called with a supported root state, we should be either in state WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT
     // or WF_STATE_ID_MEDIA_BROWSE_NAVIGATION_ROOT here
     if (workflowStateId != Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT &&
         workflowStateId != Consts.WF_STATE_ID_BROWSE_MEDIA_NAVIGATION_ROOT)
     {
       // Error case: We cannot handle the given state
       ServiceRegistration.Get<ILogger>().Warn("MediaNavigationModel: Unknown root workflow state with ID '{0}', initializing local media navigation", workflowStateId);
       // We simply use the local media mode as fallback for this case, so we go on
       workflowStateId = Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT;
     }
     mode = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? MediaNavigationMode.BrowseLocalMedia :
         MediaNavigationMode.BrowseMediaLibrary;
     IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
     AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi =>
       {
         if (mi.Aspects.ContainsKey(AudioAspect.ASPECT_ID))
           return new AudioItem(mi)
             {
                 Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
             };
         if (mi.Aspects.ContainsKey(VideoAspect.ASPECT_ID))
           return new VideoItem(mi)
             {
                 Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
             };
         if (mi.Aspects.ContainsKey(ImageAspect.ASPECT_ID))
           return new ImageItem(mi)
             {
                 Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
             };
         return null;
       };
     IEnumerable<Guid> necessaryMIATypeIDs = new Guid[]
         {
             ProviderResourceAspect.ASPECT_ID,
             MediaAspect.ASPECT_ID,
         };
     IEnumerable<Guid> optionalMIATypeIDs = new Guid[]
         {
             AudioAspect.ASPECT_ID,
             VideoAspect.ASPECT_ID,
             ImageAspect.ASPECT_ID,
         }.Union(skinDependentOptionalMIATypeIDs);
     string viewName = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ?
         Consts.RES_LOCAL_MEDIA_ROOT_VIEW_NAME : Consts.RES_BROWSE_MEDIA_ROOT_VIEW_NAME;
     ViewSpecification rootViewSpecification = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ?
         new AddedRemovableMediaViewSpecificationFacade(new LocalMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)) :
         new AddedRemovableMediaViewSpecificationFacade(new BrowseMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs));
     // Dynamic screens remain null - browse media states don't provide dynamic filters
     AbstractScreenData screenData = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ?
         (AbstractScreenData) new LocalMediaNavigationScreenData(picd) : new BrowseMediaNavigationScreenData(picd);
     Sorting.Sorting browseDefaultSorting = new BrowseDefaultSorting();
     ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
       {
           browseDefaultSorting,
           new SortByTitle(),
           new SortByDate(),
           // We could offer sortings here which are specific for one media item type but which will cope with all three item types (and sort items of the three types in a defined order)
       };
     navigationData = new NavigationData(null, viewName, workflowStateId,
         workflowStateId, rootViewSpecification, screenData, null, browseDefaultSorting)
       {
           AvailableSortings = availableSortings
       };
   }
   result.Add(Consts.KEY_NAVIGATION_MODE, mode);
   result.Add(Consts.KEY_NAVIGATION_DATA, navigationData);
   return result;
 }