Get started with WPFDevelopers controls in your WPF project in three steps.
WPFDevelopers covers the full spectrum from .NET Framework 4.0 to .NET 10:
| Framework Family | Specific Versions |
|---|
| .NET Framework | net40, net45, net451, net452, net46, net461, net462, net47, net471, net472, net48, net481 |
| .NET Core | netcoreapp3.0, netcoreapp3.1 |
| .NET 5+ | net5.0-windows, net6.0-windows, net7.0-windows, net8.0-windows, net9.0-windows, net10.0-windows |
- Visual Studio 2026
- .NET Framework 4.0 or later / .NET Core 3.0 or later
Install via NuGet Package Manager or Package Manager Console:
Install-Package WPFDevelopers
Note: For the latest features, use the preview package:
Install-Package WPFDevelopers -Pre
Or in Visual Studio: right-click your project โ Manage NuGet Packages โ search WPFDevelopers โ Install.
Add the WD namespace and theme resources in App.xaml:
<Application x:Class="YourApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- 1. Theme must be imported first -->
<ResourceDictionary Source="pack://application:,,,/WPFDevelopers;component/Themes/Theme.xaml" />
<!-- 2. wd:Resources must come AFTER Theme.xaml -->
<wd:Resources />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<wd:Resources /> supports the following modes:
| Configuration | Effect |
|---|
<wd:Resources /> | Default Light theme (follows system Light/Dark on Windows 10+) |
<wd:Resources Theme="Light" /> | Fixed light theme |
<wd:Resources Theme="Dark" /> | Fixed dark theme |
<wd:Resources Color="Fuchsia" /> | Custom theme color |
Important: wd:Resources must be placed after Theme.xaml in MergedDictionaries, otherwise the theme will not load correctly.
Declare the namespace in any XAML file:
xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
Then use WD controls:
<Window x:Class="YourApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
Title="My App" Width="800" Height="600">
<Grid>
<wd:BallLoading Width="100" IsLoading="True" />
</Grid>
</Window>
<!-- Loading animation -->
<wd:BallLoading Width="100" IsLoading="{Binding IsLoading}" />
<!-- Drawer panel -->
<wd:Drawer x:Name="DrawerTop" Position="Top">
<wd:Drawer.Header><TextBlock Text="Title" FontSize="16" /></wd:Drawer.Header>
<wd:Drawer.Content><TextBlock Text="Content" /></wd:Drawer.Content>
</wd:Drawer>
<!-- Multi-select ComboBox -->
<wd:MultiSelectComboBox ItemsSource="{Binding Items}" ShowType="Tag">
<wd:MultiSelectComboBoxItem Content="Option 1" />
<wd:MultiSelectComboBoxItem Content="Option 2" />
</wd:MultiSelectComboBox>
<!-- Step wizard -->
<wd:Step StepIndex="1">
<wd:StepItem Content="Step 1" />
<wd:StepItem Content="Step 2" />
<wd:StepItem Content="Step 3" />
</wd:Step>
<!-- Carousel -->
<wd:Carousel ItemsSource="{Binding CarouselItems}" />
<!-- Radar chart -->
<wd:ChartRadar Datas="{Binding RadarDatas}" />
<!-- Bar chart -->
<wd:ChartBar Datas="{Binding BarDatas}" />
<!-- Line chart -->
<wd:ChartLine Datas="{Binding LineDatas}" />
<!-- Pie chart (LiveCharts-style) -->
<wd:ChartPie Datas="{Binding PieDatas}" />
<!-- Dashboard gauge (NuGet version) -->
<wd:Gauge Value="75" MaxValue="100" />
<!-- Circular progress bar -->
<wd:CircleProgressBar Value="75" />
<!-- Badge notification -->
<Button wd:Badge.IsShow="True" wd:Badge.Text="new" Content="Messages" />
<!-- Button loading state -->
<Button wd:Loading.IsShow="True" wd:Loading.LoadingType="Normal" Content="Submit" />
<!-- TextBox watermark + clear button -->
<TextBox wd:ElementHelper.Watermark="Enter username" wd:ElementHelper.IsClear="True" />
<!-- PasswordBox monitoring -->
<PasswordBox wd:PasswordBoxHelper.IsMonitoring="True" wd:ElementHelper.Watermark="Password" />
<!-- DatePicker with time -->
<DatePicker wd:DatePickerHelper.ShowTime="True" />
<!-- Panel spacing -->
<WrapPanel wd:PanelHelper.Spacing="10">
<Button Content="Button 1" />
<Button Content="Button 2" />
</WrapPanel>
<!-- Corner radius -->
<Button wd:ElementHelper.CornerRadius="5" Content="Rounded" />
<TextBox wd:ElementHelper.CornerRadius="3" />
<DataGrid wd:ElementHelper.CornerRadius="3" />
<!-- Striped progress bar -->
<ProgressBar wd:ElementHelper.IsStripe="True" Value="80" />
<!-- Closable TabItem -->
<TabItem wd:ElementHelper.IsClear="True" Header="Closable Tab" />
<!-- TreeView scroll animation -->
<TreeView wd:TreeViewHelper.IsScrollAnimation="true" />
<!-- Normal button -->
<Button Style="{StaticResource WD.NormalButton}" Content="Normal" />
<!-- Primary buttons (various themes) -->
<Button Style="{StaticResource WD.PrimaryButton}" Content="Primary" />
<Button Style="{StaticResource WD.SuccessPrimaryButton}" Content="Success" />
<Button Style="{StaticResource WD.WarningPrimaryButton}" Content="Warning" />
<Button Style="{StaticResource WD.DangerPrimaryButton}" Content="Danger" />
<!-- Default buttons (various themes) -->
<Button Style="{StaticResource WD.SuccessDefaultButton}" Content="Success" />
<Button Style="{StaticResource WD.WarningDefaultButton}" Content="Warning" />
<Button Style="{StaticResource WD.DangerDefaultButton}" Content="Danger" />
WD provides a set of theme resources you can reference in XAML:
| Resource Key | Type | Description |
|---|
WD.PrimaryBrush | SolidColorBrush | Primary color |
WD.SuccessBrush | SolidColorBrush | Success color |
WD.WarningBrush | SolidColorBrush | Warning color |
WD.DangerBrush | SolidColorBrush | Danger color |
WD.InfoSolidColorBrush | SolidColorBrush | Info color |
WD.LightBrush | SolidColorBrush | Light color |
WD.CircularSingularSolidColorBrush | SolidColorBrush | Circular accent color |
WD.BackgroundBrush | SolidColorBrush | Background color |
WD.PrimaryTextBrush | SolidColorBrush | Primary text color |
WD.WarningGeometry | Geometry | Warning icon |
Important: Controls marked ๐ก Sample-only are defined in WPFDevelopers.Samples.Shared/Controls/ and are NOT part of the NuGet package (wd: namespace). They are only available in the sample project. All other controls can be used directly via the wd: prefix after NuGet installation.
MessageBox is a static message dialog class provided by WPFDevelopers, designed as a drop-in replacement for System.Windows.MessageBox with a more polished and customizable appearance.
Note: MessageBox is a static class, not a XAML control. It can only be called from C# code.
To avoid conflicts with System.Windows.MessageBox, use an alias:
using MessageBox = WPFDevelopers.Controls.MessageBox;
MessageBox.Show() provides 5 overloads:
// 1. Message text only (default OK button, no icon)
MessageBoxResult Show(string messageBoxText, Window owner = null, double? buttonRadius = null, bool isDefault = true)
// 2. Message text + caption
MessageBoxResult Show(string messageBoxText, string caption, Window owner = null, double? buttonRadius = null, bool isDefault = true)
// 3. Message text + caption + buttons
MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, Window owner = null, double? buttonRadius = null, bool isDefault = true)
// 4. Message text + caption + icon
MessageBoxResult Show(string messageBoxText, string caption, MessageBoxImage icon, Window owner = null, double? buttonRadius = null, bool isDefault = true)
// 5. Message text + caption + buttons + icon (full signature)
MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, Window owner = null, double? buttonRadius = null, bool isDefault = true)
| Parameter | Type | Default | Description |
|---|
messageBoxText | string | โ | Message content |
caption | string | โ | Dialog title |
button | MessageBoxButton | OK | Button set: OK / OKCancel / YesNo / YesNoCancel |
icon | MessageBoxImage | None | Icon type: Information / Warning / Error / Question |
owner | Window | null | Parent window. When provided, the dialog centers on the owner with an overlay mask |
buttonRadius | double? | null | Button corner radius in pixels. When null, auto-detects OS: Windows 11 defaults to 4px, Windows 10 defaults to 0px |
isDefault | bool | true | Whether the first button is the default button (triggered by Enter key) |
| MessageBoxImage | Icon | Color |
|---|
Information | Info icon | Success (green) |
Warning | Warning icon | Warning (orange) |
Error | Error icon | Danger (red) |
Question | Question icon | Primary (blue) |
// File deleted successfully, with rounded buttons
MessageBox.Show("File deleted successfully.", "Message", MessageBoxButton.OK, MessageBoxImage.Information, buttonRadius: 4);
// Uses default OK button
MessageBox.Show("Performing this action may cause the file to become inaccessible!", "Warning", MessageBoxImage.Warning);
MessageBox.Show("The file does not exist.", "Error", MessageBoxImage.Error);
var result = MessageBox.Show("The file does not exist. Continue?", "Confirm", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
switch (result)
{
case MessageBoxResult.Yes:
// User clicked "Yes"
break;
case MessageBoxResult.No:
// User clicked "No"
break;
case MessageBoxResult.Cancel:
// User clicked "Cancel" or closed the dialog
break;
}
// When owner is passed, the dialog centers on the parent window and shows an overlay mask
MessageBox.Show("Operation successful!", "Info", MessageBoxButton.OK, MessageBoxImage.Information, owner: this, buttonRadius: 4);
- Close methods: Click the close button (top-right), press
Escape, or click any button
- Owner window: When
owner is provided, the dialog centers on the parent window and displays a mask overlay. Without an owner, it auto-detects the current window or centers on screen
- Button text: Automatically localized via
LanguageManager (follows system language)
SplitButton is a split button control provided by WPFDevelopers. The left side is a clickable main button area, and the right side is a dropdown toggle button. It supports both text options and rich content options with icons.
<wd:SplitButton
Width="150"
Content="File"
ItemsSource="{Binding MenuItems}"
SelectionChanged="SplitButton_SelectionChanged" />
// ViewModel or Code-behind
public ObservableCollection<string> MenuItems { get; } = new ObservableCollection<string>
{
"Save in PDF",
"Save in Word",
"Save in Excel",
"Save in Image"
};
private void SplitButton_SelectionChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
// e.NewValue is the selected item
}
<wd:SplitButton Width="150" Content="File" ItemsSource="{Binding MenuItems}" />
<wd:SplitButton
Width="150"
Content="File"
ItemsSource="{Binding MenuItems}"
Style="{StaticResource WD.SplitButtonPrimary}" />
<wd:SplitButton
Width="150"
Background="{StaticResource WD.SuccessBrush}"
BorderBrush="{StaticResource WD.SuccessBrush}"
Content="File"
Foreground="White">
<MenuItem Header="Copy">
<MenuItem.Icon>
<wd:PathIcon Kind="Copy" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Paste" />
<MenuItem Header="Cut" />
</wd:SplitButton>
| Property | Type | Default | Description |
|---|
Content | object | null | Main button display content |
ItemsSource | object | null | Dropdown menu data source (IEnumerable) |
IsDropDownOpen | bool | false | Whether dropdown is open (two-way binding) |
ContextMenuStyle | Style | null | Custom ContextMenu style |
| Event | Description |
|---|
Click | Fired when the main button area is clicked (clicking ToggleButton does NOT fire this) |
SelectionChanged | Fired when a dropdown menu item is selected |
| Style Key | Description |
|---|
WD.SplitButton (default) | Border + transparent background, border turns primary color on hover |
WD.SplitButtonPrimary | No border + solid primary color background + white text |
| Action | Behavior |
|---|
| Click main button area | Fires Click event |
| Click ToggleButton | Expands/collapses dropdown menu |
| Click menu item | Button Content updates to selected item, fires SelectionChanged |
| Click outside menu | Automatically closes dropdown |
Carousel is a carousel control provided by WPFDevelopers, supporting auto-play, dot indicators, arrow navigation, click navigation, and more.
<wd:Carousel
Width="400" Height="200"
AutoPlay="True"
AutoPlayInterval="0:0:4"
ShowArrows="True"
ItemClick="Carousel_ItemClick">
<Border Background="#722ed1">
<TextBlock Text="Slide 1" Foreground="White" FontSize="24" />
</Border>
<Border Background="#eb2f96">
<TextBlock Text="Slide 2" Foreground="White" FontSize="24" />
</Border>
<Border Background="#1890ff">
<TextBlock Text="Slide 3" Foreground="White" FontSize="24" />
</Border>
</wd:Carousel>
<wd:Carousel
ItemsSource="{Binding ImagePaths}"
DisplayMemberPath="URL"
AutoPlay="True"
ItemClickCommand="{Binding CarouselClickCommand}" />
// Data model
public class CarouselSlideModel
{
public string Title { get; set; }
public string URL { get; set; }
}
// ViewModel
public ObservableCollection<CarouselSlideModel> ImagePaths { get; set; }
public ICommand CarouselClickCommand => new RelayCommand(param =>
{
if (param is CarouselSlideModel model)
{
Toast.Push($"Clicked image - {model.Title}", ToastImage.Success, true);
}
});
| Property | Type | Default | Description |
|---|
ItemsSource | IEnumerable | null | Data source |
SelectedIndex | int | 0 | Current selected item index |
SelectedItem | object | null | Current selected item |
AutoPlay | bool | false | Enable auto-play |
AutoPlayInterval | TimeSpan | 3 seconds | Auto-play interval |
AnimationDuration | double | 0.5 | Transition animation duration (seconds) |
ShowDots | bool | true | Show dot indicators |
ShowArrows | bool | true | Show left/right arrows |
ItemTemplate | DataTemplate | null | Data template |
DisplayMemberPath | string | null | Display member path (shows property value directly) |
| Event | Description |
|---|
ItemClick | Fired when a slide is clicked |
SelectedItemChanged | Fired when selected item changes |
| Method | Description |
|---|
GoToNext() | Navigate to next slide |
GoToPrevious() | Navigate to previous slide |
A carousel with 3D flip + zoom effects, where the center item is enlarged and highlighted:
<wd:FocusCarousel>
<Image Source="pack://application:,,,/Images/photo1.jpg" />
<Image Source="pack://application:,,,/Images/photo2.jpg" />
<Image Source="pack://application:,,,/Images/photo3.jpg" />
</wd:FocusCarousel>
A carousel with multi-layer overlay animation and auto-play/interval control:
<wd:CardCarousel AutoPlay="True" AutoPlayInterval="0:0:5">
<Image Source="pack://application:,,,/Images/photo1.jpg" />
<Image Source="pack://application:,,,/Images/photo2.jpg" />
<Image Source="pack://application:,,,/Images/photo3.jpg" />
</wd:CardCarousel>
| Property | Type | Default | Description |
|---|
AutoPlay | bool | false | Enable auto-play |
AutoPlayInterval | TimeSpan | 0:0:3 | Playback interval (TimeSpan) |
GrayscaleEffect is a pixel shader effect that converts any visual element to grayscale display, commonly used for global grayscale mode (e.g., memorial days).
<Image Source="photo.jpg">
<Image.Effect>
<wd:GrayscaleEffect Factor="1" />
</Image.Effect>
</Image>
<wd:Window>
<wd:Window.Effect>
<wd:GrayscaleEffect x:Name="grayscaleEffect" Factor="0" />
</wd:Window.Effect>
</wd:Window>
// Enable grayscale
var animation = new DoubleAnimation
{
To = 1,
Duration = TimeSpan.FromMilliseconds(1000),
EasingFunction = new SineEase { EasingMode = EasingMode.EaseOut }
};
grayscaleEffect.BeginAnimation(GrayscaleEffect.FactorProperty, animation);
// Disable grayscale
animation.To = 0;
grayscaleEffect.BeginAnimation(GrayscaleEffect.FactorProperty, animation);
| Property | Type | Default | Description |
|---|
Factor | double | 0 | Grayscale intensity, 0 = original color, 1 = full grayscale |
Brightness | double | 0 | Brightness adjustment |
OtpBox is a control designed for OTP (One-Time Password) input scenarios, supporting auto-focus jump, backspace retreat, paste fill, and more.
<wd:OtpBox Length="6" Completed="OtpBoxCompleted" />
<wd:OtpBox
Length="6"
Value="{Binding OtpCode, Mode=TwoWay}"
CompletedCommand="{Binding VerifyCommand}" />
// Event approach
private void OtpBoxCompleted(object sender, RoutedEventArgs e)
{
var otpBox = e.OriginalSource as OtpBox;
var pwd = otpBox?.Value ?? string.Empty;
if (pwd != _otpPassword)
{
myOtpBox.State = ControlState.Error;
return;
}
myOtpBox.State = ControlState.Success;
}
// Command approach
public ICommand CompletedCommand => new RelayCommand(param =>
{
var pwd = param.ToString();
// Validation logic...
});
| Property | Type | Default | Description |
|---|
Length | int | 4 | Number of OTP digits |
Value | string | "" | Current value (supports two-way binding) |
State | ControlState | None | Validation state (None/Success/Error) |
CompletedCommand | ICommand | null | Command executed on completion |
| Event | Description |
|---|
Completed | Fired when all digits are filled |
| Action | Behavior |
|---|
| Enter a digit | Auto-jump to next input box |
| Backspace (empty box) | Jump to previous box and delete last character |
| Ctrl+V Paste | Auto-fill digit by digit, filter non-numeric characters |
| Arrow keys โ โ | Switch between input boxes |
| Enter / Tab | Jump to next input box |
| Error state | Auto-clear and refocus after 1.5 seconds |
| Success state | Auto-reset to default state after 1.5 seconds |
If you prefer not to configure from scratch, reference the sample project in this repository:
src/WPFDevelopers.Samples.Shared/
โโโ App.xaml # App entry point & theme config
โโโ ExampleViews/ # Full control example pages
โ โโโ MainWindow.xaml # Main window (left menu + right content)
โ โโโ UsageGuide.xaml # Usage guide page
โ โโโ UsageColor.xaml # Color usage guide
โ โโโ BasicControlsExample.xaml # Basic control examples
โ โโโ Loading/ # Loading animation series
โ โ โโโ BallLoadingExample.xaml
โ โ โโโ RingLoadingExample.xaml
โ โ โโโ StreamerLoadingExample.xaml
โ โ โโโ WaitLoadingExample.xaml
โ โ โโโ CycleLoadingExample.xaml
โ โ โโโ RollLoadingExample.xaml
โ โโโ DrawerMenu/ # Drawer menu sub-pages
โ โ โโโ HomePage.xaml
โ โ โโโ EmailPage.xaml
โ โ โโโ EdgePage.xaml
โ โโโ NavScrollPanel/ # Nav settings panel sub-pages
โ โ โโโ About.xaml
โ โ โโโ PrivacySettings.xaml
โ โ โโโ PlaybackSettings.xaml
โ โ โโโ ShortcutKeys.xaml
โ โ โโโ DesktopLyrics.xaml
โ โโโ LoginWindow/ # Login window template
โ โ โโโ CustomControl/
โ โ โโโ CustomStyle/
โ โ โโโ LoginExample.xaml
โ โโโ CropAvatar/ # Avatar cropping
โ โ โโโ CropAvatarExample.xaml
โ โ โโโ CropAvatarWindow.xaml
โ โโโ NumberCard/ # Countdown cards
โ โ โโโ NumberCardExample.xaml
โ โ โโโ NumberCardControl.xaml
โ โโโ SpeedRockets/ # Rocket animation
โ โ โโโ SpeedRocketsExample.xaml
โ โ โโโ SpeedRocketsMini.xaml
โ โโโ ZooSemy/ # Skeuomorphic knob
โ โ โโโ ZooSemyExample.xaml
โ โ โโโ VolumeControl.xaml
โ โโโ CanvasHandWriting/ # Handwriting
โ โ โโโ CanvasHandWritingExample.xaml
โ โโโ Desktop/ # Desktop wallpaper
โ โ โโโ DesktopBackground.xaml
โ โ โโโ DesktopPlayVideo.xaml
โ โโโ Passwrod/ # Password controls
โ โ โโโ PasswordExample.xaml
โ โ โโโ PasswordWithPlainText.xaml
โ โโโ Map/ # Map
โ โ โโโ BingAMapExample.xaml
โ โโโ DrapView/ # Drag view
โ โ โโโ DrapViewExample.xaml
โ โโโ ... (more example files)
โโโ Controls/ # Sample helper controls (CodeViewer, NavigateMenu, etc.)
โโโ ViewModels/ # Sample ViewModels
โโโ Models/ # Data models
โโโ Helpers/MenuEnum.cs # All example category enum
โโโ Converts/ # Value converters
Each example page includes a built-in code viewer (CodeViewer) that lets you inspect the corresponding XAML/C# source code directly.