Implements IValueConverter as MarkupExtension for direct XAML usage without StaticResource. Use when creating converters to eliminate resource dictionary declarations.
View on GitHubchristian289/dotnet-with-claudecode
wpf-dev-pack
wpf-dev-pack/skills/using-converter-markup-extension/SKILL.md
January 23, 2026
Select agents to install to:
npx add-skill https://github.com/christian289/dotnet-with-claudecode/blob/main/wpf-dev-pack/skills/using-converter-markup-extension/SKILL.md -a claude-code --skill using-converter-markup-extensionInstallation paths:
.claude/skills/using-converter-markup-extension/# Using Converter Markup Extension
Combine `MarkupExtension` with `IValueConverter` for direct XAML usage without resource declarations.
## Why Markup Extension Converters?
| Aspect | StaticResource Converter | MarkupExtension Converter |
|--------|-------------------------|--------------------------|
| Declaration | Required in Resources | Not required |
| XAML Usage | `{StaticResource MyConverter}` | `{local:MyConverter}` |
| Singleton | Manual implementation | Built-in lazy singleton |
| Boilerplate | More | Less |
---
## Base Classes
### IValueConverter Base (.NET 7+)
```csharp
namespace MyApp.Converters;
public abstract class ConverterMarkupExtension<T> : MarkupExtension, IValueConverter
where T : class, new()
{
private static readonly Lazy<T> _converter = new(() => new T());
public override object ProvideValue(IServiceProvider serviceProvider)
{
return _converter.Value;
}
public abstract object? Convert(
object? value,
Type targetType,
object? parameter,
CultureInfo culture);
public virtual object? ConvertBack(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
throw new NotSupportedException();
}
}
```
### IMultiValueConverter Base
```csharp
namespace MyApp.Converters;
public abstract class MultiConverterMarkupExtension<T> : MarkupExtension, IMultiValueConverter
where T : class, new()
{
private static readonly Lazy<T> _converter = new(() => new T());
public override object ProvideValue(IServiceProvider serviceProvider)
{
return _converter.Value;
}
public abstract object? Convert(
object?[] values,
Type targetType,
object? parameter,
CultureInfo culture);
public virtual object?[] ConvertBack(
object? value,
Type[] targetTypes,
object? parameter,
CultureInfo culture)
{
throw new NotSupportedExcepti