This document provides a comprehensive overview of the Screenbox project's architecture, organization, and practical workflows for development.
- 📖 Overview
- 🏗️ Solution Structure
- 🎨 View Layer
- 🔄 ViewModel Layer
- 🔧 Model Layer
- 🏛️ Architecture Rules
- 🧰 Technology Stack
- 📋 Development Guidelines
Screenbox is a modern media player for Windows built using the Universal Windows Platform (UWP) and LibVLCSharp. The application follows the Model-View-ViewModel (MVVM) design pattern with dependency injection for maintainable and testable code.
The architecture is built around clean separation of concerns:
- View Layer: XAML-based UI components and user controls
- ViewModel Layer: Presentation logic and data binding with MVVM
- Model Layer: Business logic, services, and media playback engine
The solution contains several projects organized for clear separation of concerns:
Screenbox.slnx
├── Screenbox/ # Main UWP application
├── Screenbox.Core/ # Core services, models, view models, and playback logic
├── Screenbox.UI/ # Shared UI components and custom controls
├── Screenbox.VideoView/ # Video rendering helper for playback surfaces
├── Screenbox.Lively/ # Lively Wallpaper integration support
└── Screenbox.Core.Tests/ # Unit and integration tests for the core library
The main project is the user-facing Windows application. It owns the shell, pages, controls, dialogs, flyouts, localization, and app startup wiring.
The core project contains the business logic, services, domain models, view models, contexts, coordinators, playback abstractions, and the app-wide messenger contracts.
This library contains shared UI components, theme resources, and templated controls that can be reused across different parts of the application.
The VideoView project provides a helper for rendering video playback surfaces, abstracting the underlying video rendering implementation.
The Lively project provides integration support for Lively Wallpaper, allowing the application to interact with and control live wallpapers.
The Core.Tests project contains unit and integration tests for the core logic, ensuring the correctness and reliability of the application's business logic.
The View layer is contained in the Screenbox project. This project consists primarily of XAML files and custom controls that define the user interface. App.xaml and the Styles folder contain resources referenced throughout the application, while the App.xaml.cs file serves as the main entry point and handles dependency injection configuration.
Screenbox uses a single-page application model with MainPage.xaml as the root container. The main page utilizes a NavigationView control for the navigation menu and houses content frames for different application modes:
MainPage.xaml (Root Container)
├── NavigationView (Menu System)
├── ContentFrame (Dynamic Content)
└── PlayerPage.xaml (Media Player Overlay)
The application organizes its content into several main page categories:
HomePage.xaml: Recently accessed mediaVideosPage.xaml: Video library browsing with nested pages for categoriesMusicPage.xaml: Music library with artist, album, and song viewsNetworkPage.xaml: Network streaming and casting featuresPlayQueuePage.xaml: Current play queue and queue managementPlaylistsPage.xaml: Playlist creation and managementSettingsPage.xaml: Application configuration and preferences
Screenbox implements numerous custom controls for specialized functionality:
PlayerControls.xaml: Primary media control interfaceSeekBar.xaml: Timeline scrubbing and progress indicationVolumeControl.xaml: Audio level managementPlayerElement.xaml: Main video rendering surface
MediaListViewItem.xaml: Templated list items for media contentCommonGridViewItem.xaml: Grid layout for media thumbnailsPlayQueueControl.xaml: Specialized play queue display component
PropertiesDialog.xaml: Media file information displayOpenUrlDialog.xaml: Network URL input interface
Visual States enable adaptive layouts that respond to window size changes, device orientation, and user interaction modes. Screenbox uses visual states extensively to create responsive experiences across different form factors.
Screenbox uses data binding extensively to create dynamic, responsive UI components. The application primarily uses the x:Bind markup extension for performance benefits over the legacy Binding syntax.
Example of x:Bind usage in media display:
<TextBlock Text="{x:Bind ViewModel.CurrentMedia.Title, Mode=OneWay}" />
<ProgressBar Value="{x:Bind ViewModel.PlaybackPosition, Mode=OneWay}" />The binding system enables automatic UI updates when media state changes, providing smooth user experiences without manual UI manipulation code.
Navigation in Screenbox is handled through a custom NavigationService that maps ViewModels to their corresponding Pages. This system is configured in App.xaml.cs and enables loose coupling between the ViewModel and View layers:
new KeyValuePair<Type, Type>(typeof(HomePageViewModel), typeof(HomePage)),
new KeyValuePair<Type, Type>(typeof(VideosPageViewModel), typeof(VideosPage)),
new KeyValuePair<Type, Type>(typeof(MusicPageViewModel), typeof(MusicPage))Screenbox implements comprehensive multi-language support through the Windows and ReswPlus resource system, following UWP localization guidelines and ReswPlus guides for efficient localized resource management.
The ViewModel layer is contained in the Screenbox.Core project and serves as the intermediary between the UI components and business logic. ViewModels provide data sources for UI binding and encapsulate presentation logic while remaining independent of specific UI implementations.
MainPageViewModel.cs: Root application state and navigation coordinationPlayerPageViewModel.cs: Media playback state and control logicPlayerControlsViewModel.cs: Playback control interactions and stateSettingsPageViewModel.cs: Application configuration management
PlayQueuePanelViewModel.cs: ViewModel for the play queue panel/flyout — handles item selection, reordering, and adding files or URLs to the queueCommonViewModel.cs: Shared state across multiple pagesMediaViewModel.cs: Individual media item representationPlaylistViewModel.cs: Playlist-specific functionality
HomePageViewModel.cs: Recent mediaVideosPageViewModel.cs: Video library browsingMusicPageViewModel.cs: Music library organizationSearchResultPageViewModel.cs: Search functionality and results
Some ViewModels — specifically MediaViewModel, AlbumViewModel, and ArtistViewModel — serve a dual role: they are MVVM observables and the effective domain entities for media items. This is a deliberate pragmatic choice for UWP MVVM: the application domain is inherently observable (tracks must notify when metadata loads, albums notify when thumbnails change), so the domain model and the observable layer naturally coincide.
As a result, these classes appear throughout the codebase in all layers — including LibraryContext, PlaylistsContext, and SearchResult — without violating the intended architecture. They should be thought of as observable domain entities rather than pure presentation objects, and should never contain XAML or UI framework references.
ViewModels implement property change notification through the CommunityToolkit.Mvvm framework. Most ViewModels inherit from ObservableObject or use source generators to implement INotifyPropertyChanged automatically:
[ObservableProperty]
private partial string CurrentMediaTitle { get; set; }
[ObservableProperty]
private partial TimeSpan PlaybackPosition { get; set; }This enables automatic UI updates when ViewModel properties change, maintaining synchronization between the data layer and user interface.
Screenbox uses the CommunityToolkit.Mvvm messaging system for decoupled communication between components. This allows ViewModels, Services, and other components to communicate without direct references.
Playback Control Messages
PlayMediaMessage.cs: Initiate media playbackTogglePlayPauseMessage.cs: Toggle playback stateChangeTimeRequestMessage.cs: Seek to specific time position
UI State Messages
PlayerControlsVisibilityChangedMessage.cs: Show/hide player controlsSettingChangedMessage.cs: Strongly-typed domain setting modification notificationsNavigationViewDisplayModeRequestMessage.cs: Navigation menu state changesNotificationMessage.cs: Show notifications inside the appPlayerOsdUpdateMessage.cs: On-screen display updates for playback information
System Integration Messages
SuspendingMessage.cs: Application lifecycle events
The Model layer contains the core business logic and is primarily located in the Screenbox.Core project. This layer consists of services, media playback components, and data models that provide the foundation for the application functionality.
Screenbox implements a comprehensive service-oriented architecture using Microsoft.Extensions.DependencyInjection for service registration and resolution. Services are registered in ServiceHelpers.cs and injected throughout the application.
Media Management Services
IFilesService: File system operations and media discoveryILibraryService: Stateless operations for fetching and managing libraries.FetchMusicAsyncreturns aMusicLibraryand accepts an optionalIProgress<MusicLibrary>for incremental batch updates;FetchVideosAsyncworks analogously withVideosLibrary.ISearchService: Content search and filtering functionality
Playback and Streaming Services
IPlayerService: Media player initialization and playback item managementICastService: Stateless casting operations for renderer creation and configurationISystemMediaTransportControlsService: Windows media key integration
Persistence Services
IDatabaseService: Low-level SQLite database management. Opens (or creates)screenbox.dbinApplicationData.Current.LocalFolder, applies the schema on first open, and exposesCreateConnection()for typed data access. The library tables are rebuildable cache data, but playlists are durable user data. If schema initialization fails with a SQLite or I/O error, the current fallback deletes and recreates the database file, which can also erase playlists. Registered as a singleton and initialized early at app startup.IPlaybackProgressTracker: Tracks and persists the playback progress for each media item, enabling resume-from-position functionality. Handles theSuspendingMessageto flush state to the database on app suspension.
System Integration Services
ISettingsStorage: Low-level application configuration persistenceIWindowService: Window management and display operations
Contexts are observable application state holders shared across services and ViewModels. They represent the current runtime state of a domain area and act as the single source of truth for that state within the app.
Architectural rules for contexts:
- Written by: Services and coordinators (as a side effect of use-case execution)
- Read/observed by: ViewModels (via data binding and property-changed events)
- Must not: Call services or coordinators back (no circular dependencies)
- May contain: Messenger helper methods that broadcast state change events
Available contexts:
PlayerContext: Holds the currentIMediaPlayerinstance, allowing components to observe player state changesCastContext: Holds casting state including the active renderer watcher and selected rendererLibraryContext: Holds library state including theStorageLibraryhandles (MusicStorageLibrary,VideosStorageLibrary), loading flags, and the currentMusicLibraryandVideosLibrarycontainer objects. Written atomically byLibraryCoordinatorafter each fetch batch or on completion.PlaylistsContext: Holds the application-wide collection of user playlistsPlayQueueContext: Holds the global play queue state —Items(the orderedObservableCollection<MediaViewModel>),CurrentItem,CurrentIndex,ShuffleMode, andRepeatMode. Written exclusively byPlayQueueCoordinator; observed by any ViewModel that needs play queue state.
Some platform APIs (file system watchers, timers, device watchers) require stateful ownership to reliably subscribe/unsubscribe and to avoid duplicating watchers across views. Coordinators own these long-lived resources and orchestrate service calls in response to platform events.
Architectural rules for coordinators:
- Depend on: Services and contexts (never on ViewModels)
- Consumed by: ViewModels at initialization boundaries (to start lifecycle)
- Must expose: An interface (
ILibraryCoordinator, etc.) for testability - Implement:
IDisposableto clean up watchers/timers
Available coordinators:
LibraryCoordinator/ILibraryCoordinator: Stateful coordinator that owns libraryStorageFileQueryResultwatchers, debounce timers, and Xbox removable-storage device watchers. CallsILibraryService.FetchMusicAsync/FetchVideosAsyncwith anIProgress<T>handler that updatesLibraryContext.Music/LibraryContext.Videosincrementally as each batch arrives, then applies the final result on completion. This provides live UI progress updates during long library scans.PlayQueueCoordinator/IPlayQueueCoordinator: Stateful coordinator that owns the global play queue for the app session. HandlesPlayMediaMessage,SetQueueMessage,ClearQueueMessage, andQueueRequestMessage. Wires Windows System Media Transport Controls (hardware media keys, repeat mode). Pre-buffers thumbnails for items adjacent to the current position. DrivesPlayQueueContextstate as a side effect of all queue mutations.
Helper classes provide focused utilities and lightweight wrappers for specific functionality:
RendererWatcher: Lightweight wrapper around VLC's RendererDiscoverer for network renderer discovery, exposing events for renderer found/lost notifications and maintaining a list of available renderersDisplayRequestTracker: Manages display sleep prevention during media playback
The media playback system is built on LibVLCSharp with custom abstractions for integration with the MVVM architecture:
IMediaPlayer: Media player abstraction interfaceIPlaybackItem: Playback item interface with track, chapter, and timing abstractionsVlcMediaPlayer.cs: VLC-based implementation of media playerVlcPlaybackItem.cs: VLC-backed implementation of playback item
- VlcAudioTrackList.cs: Audio track selection and switching
- VlcVideoTrackList.cs: Video track and subtitle management
- VlcSubtitleTrackList.cs: Subtitle track handling
- VlcChapterList.cs: Chapter navigation support
The playback engine provides a clean interface for the ViewModel layer while abstracting the complexities of the underlying VLC media framework.
MediaInfo.cs: Base media file informationVideoInfo.cs: Video-specific metadata and propertiesMusicInfo.cs: Audio metadata and music library information
MusicLibrary.cs: Immutable snapshot of the music library —Songs,Albums,Artists,UnknownAlbum, andUnknownArtist. Replaced by a new instance whenever the library is refreshed, so all relationships stay consistent. Has a staticEmptyinstance used as the initialLibraryContext.Musicvalue.VideosLibrary.cs: Immutable snapshot of the video library —Videoslist. Same replacement model asMusicLibrary.RawMediaRecordDto.cs: Serializable snapshot of a media item's metadata (title, path, duration, year, type, and type-specific properties). Used as the unit of persistence for playlist items and as an intermediate representation when reading the media-records cache from the database.
The library tables in screenbox.db (SQLite, LocalFolder) are rebuildable cache data. The playlists and playlist_items tables contain durable user data and are not disposable. A missing database is created on startup; if schema initialization fails with a SQLite or I/O error, the current fallback recreates the whole file, which can also erase playlists.
| Table | Purpose |
|---|---|
library_folders |
Tracks which folders belong to the music and video libraries |
media_records |
Caches media-file metadata indexed by path; queried instead of crawling disk on subsequent launches |
playback_progress |
Stores the last playback position per media location for resume-from-position |
playlists |
One row per saved playlist (id, display name, last-updated timestamp) |
playlist_items |
Ordered list of media snapshots for each playlist; cascade-deleted with the parent playlist |
The following table summarizes the allowed dependency directions between layers:
| Layer | May depend on | Must not depend on |
|---|---|---|
| View (XAML + code-behind) | ViewModels, Contexts (read-only via DI) | Services, Coordinators directly |
| ViewModels | Services (via interface), Contexts, Factories | Coordinators (except at startup boundaries) |
| Contexts | Models, Playback abstractions | Services, Coordinators, ViewModels |
| Coordinators | Services (via interface), Contexts | ViewModels |
| Services | Other Services (via interface), Models, Playback | ViewModels, Contexts |
| Models / Playback | (no application dependencies) | All layers above |
- All services and coordinators must be registered against their interface, not their concrete type.
- Use constructor injection exclusively. The service locator pattern (
Ioc.Default.GetRequiredService<T>()) is acceptable only in View code-behind for resolving ViewModels into pageDataContext. It must not be used inside ViewModels, Services, or Coordinators.
- Stateless services (e.g.,
LibraryService,CastService): execute operations and return data to the caller. They do not own long-lived observable state, and must not read from or write to aContextdirectly. Results are returned as plain models (e.g.,MusicLibrary) and applied to the context by the coordinator. - Stateful coordinators (e.g.,
LibraryCoordinator): own watchers/timers and manage subscriptions/lifetimes. Register as singletons and implementIDisposable. - Stateful services (e.g.,
PlaybackProgressTracker): own in-memory state but no platform subscriptions. Prefer a service interface; register as singletons.
- UWP (Universal Windows Platform): Windows application framework providing native performance and system integration
- .NET 10: Cross-platform runtime for building modern applications
- XAML: Declarative markup for user interface definition
- LibVLCSharp: Cross-platform media playback engine with extensive codec support
- CommunityToolkit.Mvvm: MVVM framework for property change notification, messaging, and source generation
- Visual Studio 2026: Primary integrated development environment
- MSBuild: Build system and project management
- XAML Styler: XAML formatting and style enforcement
- Microsoft.UI.Xaml - WinUI controls and modern UI components
- CommunityToolkit.Mvvm - MVVM helpers, messaging, and source generators
- CommunityToolkit.Uwp - UWP community extensions
- Microsoft.Extensions.DependencyInjection - Service container and dependency injection
- LibVLCSharp - VLC media player integration
- TagLibSharp - Audio metadata reading
- Microsoft.Data.Sqlite - SQLite database access for media library cache and playlist persistence
- Sentry - Error tracking and performance monitoring
- Sentry.Extensions.Logging - Sentry provider for
Microsoft.Extensions.Loggingwith breadcrumb/event integration - Microsoft.Extensions.Logging - Unified structured logging API used across Core and app layers
Follow C# coding conventions and UWP best practices throughout the codebase.
Adhere to .NET naming guidelines:
- PascalCase: Classes, methods, properties, public fields, enums
- camelCase: Local variables, parameters, private fields
- Interfaces: Prefixed with
I(e.g.,IMediaPlayer) - Private fields: Prefixed with
_(e.g.,_settingsService) - XAML resources: Descriptive, consistent naming patterns
- One class per file
- Nested namespaces match folder structure
- Partial classes for XAML code-behind
- Use
async/awaitfor I/O operations following async best practices - Proper
ConfigureAwait(false)usage in library code - Task-based operations for file system access
- Follow .NET memory management guidelines
- Use weak references for event handlers where appropriate
- Follow UWP performance best practices
- Enable virtualization for large collections
- Implement proper image caching
- Process heavy operations on background threads
- x86: 32-bit Intel/AMD processors
- x64: 64-bit Intel/AMD processors
- ARM64: 64-bit ARM processors
- Debug: Development builds with debugging symbols
- Release: Optimized production builds
For detailed build configuration, see UWP packaging documentation.
- UWP Developer Guide
- C# Programming Reference
- MVVM Toolkit Documentation
- Dependency Injection in .NET
This structure enables maintainable, scalable development while supporting the rich feature set of a modern media player application.