integrating-wpf-media
SKILL.md
WPF Media Integration Patterns
Integrating multimedia content such as images, video, and audio in WPF.
1. Image Control
1.1 Basic Image Display
<!-- Resource image -->
<Image Source="/Assets/logo.png" Width="100" Height="100"/>
<!-- Absolute path -->
<Image Source="C:\Images\photo.jpg"/>
<!-- URI -->
<Image Source="https://example.com/image.png"/>
<!-- Pack URI (embedded resource) -->
<Image Source="pack://application:,,,/MyAssembly;component/Images/icon.png"/>
1.2 Stretch Options
<!-- None: maintain original size -->
<Image Source="/photo.jpg" Stretch="None"/>
<!-- Fill: stretch to fit area (ignore aspect ratio) -->
<Image Source="/photo.jpg" Stretch="Fill"/>
<!-- Uniform: maintain aspect ratio, maximum size within area -->
<Image Source="/photo.jpg" Stretch="Uniform"/>
<!-- UniformToFill: maintain aspect ratio, fill area (may crop) -->
<Image Source="/photo.jpg" Stretch="UniformToFill"/>
1.3 Dynamic Image Loading
namespace MyApp.Helpers;
using System;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;
public static class ImageHelper
{
/// <summary>
/// Load image from file
/// </summary>
public static BitmapImage LoadFromFile(string filePath)
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(filePath, UriKind.Absolute);
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
bitmap.Freeze(); // Can be used outside UI thread
return bitmap;
}
/// <summary>
/// Load image from stream
/// </summary>
public static BitmapImage LoadFromStream(Stream stream)
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = stream;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
bitmap.Freeze();
return bitmap;
}
/// <summary>
/// Load thumbnail (memory optimization)
/// </summary>
public static BitmapImage LoadThumbnail(string filePath, int maxWidth, int maxHeight)
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(filePath, UriKind.Absolute);
bitmap.DecodePixelWidth = maxWidth;
bitmap.DecodePixelHeight = maxHeight;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
bitmap.Freeze();
return bitmap;
}
/// <summary>
/// Load image from Base64
/// </summary>
public static BitmapImage LoadFromBase64(string base64)
{
var bytes = Convert.FromBase64String(base64);
using var stream = new MemoryStream(bytes);
return LoadFromStream(stream);
}
}
1.4 Image Load Events
// XAML
// <Image x:Name="DynamicImage" ImageFailed="OnImageFailed"/>
private void LoadImageAsync(string url)
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(url);
bitmap.EndInit();
// Loading complete event
bitmap.DownloadCompleted += (s, e) =>
{
// Image load complete
};
// Loading failed event
bitmap.DownloadFailed += (s, e) =>
{
// Error handling
};
// Loading progress
bitmap.DownloadProgress += (s, e) =>
{
var progress = e.Progress; // 0-100
};
DynamicImage.Source = bitmap;
}
2. MediaElement (Video/Audio)
2.1 Basic Usage
<!-- Auto-play video -->
<MediaElement Source="/Videos/intro.mp4"
LoadedBehavior="Play"
UnloadedBehavior="Stop"/>
<!-- Manual control video -->
<MediaElement x:Name="VideoPlayer"
Source="/Videos/movie.mp4"
LoadedBehavior="Manual"
UnloadedBehavior="Stop"
MediaOpened="OnMediaOpened"
MediaEnded="OnMediaEnded"
MediaFailed="OnMediaFailed"/>
2.2 LoadedBehavior Options
| Value | Description |
|---|---|
| Play | Auto-play |
| Pause | Pause after load |
| Stop | Stop after load |
| Manual | Control via code |
| Close | Close media |
2.3 Video Player Implementation
namespace MyApp.Controls;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
public sealed partial class VideoPlayerControl : UserControl
{
private readonly DispatcherTimer _positionTimer;
private bool _isDragging;
public VideoPlayerControl()
{
InitializeComponent();
_positionTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(200)
};
_positionTimer.Tick += OnPositionTimerTick;
}
private void OnMediaOpened(object sender, RoutedEventArgs e)
{
// Display total duration
if (VideoPlayer.NaturalDuration.HasTimeSpan)
{
var duration = VideoPlayer.NaturalDuration.TimeSpan;
PositionSlider.Maximum = duration.TotalSeconds;
TotalTimeText.Text = FormatTime(duration);
}
_positionTimer.Start();
}
private void OnMediaEnded(object sender, RoutedEventArgs e)
{
_positionTimer.Stop();
VideoPlayer.Stop();
VideoPlayer.Position = TimeSpan.Zero;
}
private void OnMediaFailed(object sender, ExceptionRoutedEventArgs e)
{
// Media load failed
MessageBox.Show($"Media load failed: {e.ErrorException.Message}");
}
private void OnPositionTimerTick(object? sender, EventArgs e)
{
if (!_isDragging)
{
PositionSlider.Value = VideoPlayer.Position.TotalSeconds;
CurrentTimeText.Text = FormatTime(VideoPlayer.Position);
}
}
private void PlayButton_Click(object sender, RoutedEventArgs e)
{
VideoPlayer.Play();
_positionTimer.Start();
}
private void PauseButton_Click(object sender, RoutedEventArgs e)
{
VideoPlayer.Pause();
}
private void StopButton_Click(object sender, RoutedEventArgs e)
{
VideoPlayer.Stop();
_positionTimer.Stop();
}
private void PositionSlider_DragStarted(object sender, EventArgs e)
{
_isDragging = true;
}
private void PositionSlider_DragCompleted(object sender, EventArgs e)
{
_isDragging = false;
VideoPlayer.Position = TimeSpan.FromSeconds(PositionSlider.Value);
}
private void VolumeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
VideoPlayer.Volume = e.NewValue;
}
private static string FormatTime(TimeSpan time)
{
return time.Hours > 0
? $"{time:hh\\:mm\\:ss}"
: $"{time:mm\\:ss}";
}
}
2.4 VideoPlayerControl XAML
<UserControl x:Class="MyApp.Controls.VideoPlayerControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Video area -->
<MediaElement x:Name="VideoPlayer"
LoadedBehavior="Manual"
UnloadedBehavior="Stop"
MediaOpened="OnMediaOpened"
MediaEnded="OnMediaEnded"
MediaFailed="OnMediaFailed"/>
<!-- Control bar -->
<Grid Grid.Row="1" Background="#CC000000">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button x:Name="PlayButton" Content="▶" Click="PlayButton_Click"
Grid.Column="0" Margin="5"/>
<Button x:Name="PauseButton" Content="⏸" Click="PauseButton_Click"
Grid.Column="1" Margin="5"/>
<Button x:Name="StopButton" Content="⏹" Click="StopButton_Click"
Grid.Column="2" Margin="5"/>
<!-- Position slider -->
<Slider x:Name="PositionSlider"
Grid.Column="3"
Margin="5"
VerticalAlignment="Center"
Thumb.DragStarted="PositionSlider_DragStarted"
Thumb.DragCompleted="PositionSlider_DragCompleted"/>
<!-- Time display -->
<StackPanel Grid.Column="4" Orientation="Horizontal"
VerticalAlignment="Center" Margin="5">
<TextBlock x:Name="CurrentTimeText" Foreground="White" Text="00:00"/>
<TextBlock Foreground="White" Text=" / "/>
<TextBlock x:Name="TotalTimeText" Foreground="White" Text="00:00"/>
</StackPanel>
<!-- Volume slider -->
<Slider x:Name="VolumeSlider"
Grid.Column="5"
Width="80"
Margin="5"
Minimum="0" Maximum="1" Value="0.5"
VerticalAlignment="Center"
ValueChanged="VolumeSlider_ValueChanged"/>
</Grid>
</Grid>
</UserControl>
3. Audio Playback
3.1 Audio with MediaElement
<MediaElement x:Name="AudioPlayer"
Source="/Sounds/background.mp3"
LoadedBehavior="Manual"
Volume="0.5"/>
3.2 SoundPlayer (Simple WAV)
namespace MyApp.Services;
using System.Media;
public sealed class SoundService
{
private readonly SoundPlayer _clickSound;
private readonly SoundPlayer _notificationSound;
public SoundService()
{
// WAV files only
_clickSound = new SoundPlayer("Sounds/click.wav");
_notificationSound = new SoundPlayer("Sounds/notification.wav");
// Preload
_clickSound.Load();
_notificationSound.Load();
}
public void PlayClick()
{
_clickSound.Play(); // Async playback
}
public void PlayNotification()
{
_notificationSound.PlaySync(); // Sync playback
}
}
3.3 SoundPlayerAction (Sound in XAML)
<Button Content="Click Me">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<SoundPlayerAction Source="/Sounds/click.wav"/>
</EventTrigger>
</Button.Triggers>
</Button>
4. Image Gallery & Performance
For gallery implementation and optimization, see references/media-gallery.md:
- Gallery ViewModel: MVVM pattern with thumbnail loading
- Gallery View: ListBox with virtualization
- Performance Optimization: DecodePixelWidth, Freeze(), lazy loading
5. References
Weekly Installs
4
Repository
christian289/do…audecodeGitHub Stars
16
First Seen
Feb 28, 2026
Security Audits
Installed on
gemini-cli4
opencode4
codebuddy4
github-copilot4
codex4
kimi-cli4