From wpf-dev-pack
Generates WPF IValueConverter or IMultiValueConverter classes with MarkupExtension pattern for direct XAML usage. Invoke via /wpf-dev-pack:make-wpf-converter for new converters or MultiValueConverter scaffolding.
npx claudepluginhub christian289/dotnet-with-claudecode --plugin wpf-dev-packThis skill uses the workspace's default tool permissions.
**If `$0` is empty, use the AskUserQuestion tool to ask: "Enter the Converter name (e.g., BoolToVisibility, NullToVisibility)". Do NOT proceed until a valid name is provided. Use the response as the ConverterName for all subsequent steps.**
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
If $0 is empty, use the AskUserQuestion tool to ask: "Enter the Converter name (e.g., BoolToVisibility, NullToVisibility)". Do NOT proceed until a valid name is provided. Use the response as the ConverterName for all subsequent steps.
Generate a $0Converter class with MarkupExtension pattern for direct XAML usage.
If multi is appended to the arguments, generate IMultiValueConverter instead of IValueConverter.
{Namespace} with the project's root namespace detected from csproj or existing code.{SourceType} and {TargetType} with the appropriate types based on the converter name (e.g., BoolToVisibility → bool, Visibility).{Project} with the target project path.# IValueConverter
/wpf-dev-pack:make-wpf-converter BoolToVisibility
# IMultiValueConverter
/wpf-dev-pack:make-wpf-converter AllTrue multi
Create this base class first in your Converters folder:
namespace {Namespace}.Converters;
/// <summary>
/// Base class for converters that can be used directly in XAML without resource declaration.
/// </summary>
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("ConvertBack is not supported.");
}
}
namespace {Namespace}.Converters;
/// <summary>
/// Base class for multi-value converters with MarkupExtension support.
/// </summary>
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 NotSupportedException("ConvertBack is not supported.");
}
}
namespace {Namespace}.Converters;
/// <summary>
/// Converts {SourceType} to {TargetType}.
/// </summary>
public sealed class $0Converter : ConverterMarkupExtension<$0Converter>
{
public override object? Convert(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
// TODO: Implement conversion logic
if (value is not {SourceType} source)
{
return DependencyProperty.UnsetValue;
}
return source; // Replace with actual conversion
}
}
namespace {Namespace}.Converters;
/// <summary>
/// Combines multiple values into a single result.
/// </summary>
public sealed class $0Converter : MultiConverterMarkupExtension<$0Converter>
{
public override object? Convert(
object?[] values,
Type targetType,
object? parameter,
CultureInfo culture)
{
// Validate input values
if (values is null || values.Length < 2)
{
return DependencyProperty.UnsetValue;
}
// Check for unset values
if (values.Any(v => v == DependencyProperty.UnsetValue))
{
return DependencyProperty.UnsetValue;
}
// TODO: Implement multi-value conversion logic
return values;
}
}
<Window xmlns:conv="clr-namespace:MyApp.Converters">
<!-- No resource declaration needed! -->
<TextBlock Visibility="{Binding IsVisible, Converter={conv:BoolToVisibilityConverter}}"/>
<!-- With parameter -->
<TextBlock Visibility="{Binding IsHidden, Converter={conv:BoolToVisibilityConverter}, ConverterParameter=Invert}"/>
</Window>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{conv:FullNameConverter}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
public sealed class BoolToVisibilityConverter : ConverterMarkupExtension<BoolToVisibilityConverter>
{
public override object? Convert(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
if (value is not bool boolValue)
return Visibility.Collapsed;
var invert = parameter is "Invert" or "invert";
return (boolValue ^ invert) ? Visibility.Visible : Visibility.Collapsed;
}
}
public sealed class NullToVisibilityConverter : ConverterMarkupExtension<NullToVisibilityConverter>
{
public override object? Convert(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
var isNull = value is null;
var invert = parameter is "Invert";
return (isNull ^ invert) ? Visibility.Collapsed : Visibility.Visible;
}
}
public sealed class InverseBoolConverter : ConverterMarkupExtension<InverseBoolConverter>
{
public override object? Convert(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
if (value is not bool boolValue)
return false;
return !boolValue;
}
public override object? ConvertBack(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
if (value is not bool boolValue)
return false;
return !boolValue;
}
}
{Project}/
└── Converters/
├── ConverterMarkupExtension.cs # Base class
├── MultiConverterMarkupExtension.cs # Multi base class
├── BoolToVisibilityConverter.cs
├── NullToVisibilityConverter.cs
└── $0Converter.cs
global using System;
global using System.Globalization;
global using System.Linq;
global using System.Windows;
global using System.Windows.Data;
global using System.Windows.Markup;
| Aspect | StaticResource | MarkupExtension |
|---|---|---|
| Resource declaration | Required | Not required |
| XAML usage | {StaticResource Key} | {local:Converter} |
| Singleton | Manual | Built-in (Lazy) |
| Boilerplate | More | Less |
using-converter-markup-extension - Detailed MarkupExtension patternadvanced-data-binding - MultiBinding patterns