Skill v1.0.1
currentAutomated scan100/100+1 new
version: "1.0.1" description: "Generates WPF IValueConverter or IMultiValueConverter classes with MarkupExtension pattern. Use when creating a new value converter, scaffolding a MultiValueConverter, or adding a converter with direct XAML usage. Usage: /wpf-dev-pack:make-wpf-converter <ConverterName> [multi]" argument-hint: [ConverterName]
WPF Converter Generator
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.
- Replace
{Namespace}with the project's root namespace detected from csproj or existing code. - Replace
{SourceType}and{TargetType}with the appropriate types based on the converter name (e.g., BoolToVisibility → bool, Visibility). - Replace
{Project}with the target project path.
Usage
# IValueConverter/wpf-dev-pack:make-wpf-converter BoolToVisibility# IMultiValueConverter/wpf-dev-pack:make-wpf-converter AllTrue multi
Generated Code
Base Class (ConverterMarkupExtension.cs)
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, IValueConverterwhere 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.");}}
Base Class (MultiConverterMarkupExtension.cs)
namespace {Namespace}.Converters;/// <summary>/// Base class for multi-value converters with MarkupExtension support./// </summary>public abstract class MultiConverterMarkupExtension<T> : MarkupExtension, IMultiValueConverterwhere 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.");}}
IValueConverter
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 logicif (value is not {SourceType} source){return DependencyProperty.UnsetValue;}return source; // Replace with actual conversion}}
IMultiValueConverter
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 valuesif (values is null || values.Length < 2){return DependencyProperty.UnsetValue;}// Check for unset valuesif (values.Any(v => v == DependencyProperty.UnsetValue)){return DependencyProperty.UnsetValue;}// TODO: Implement multi-value conversion logicreturn values;}}
XAML Usage
MarkupExtension Pattern (Recommended)
<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>
MultiBinding
<TextBlock><TextBlock.Text><MultiBinding Converter="{conv:FullNameConverter}"><Binding Path="FirstName"/><Binding Path="LastName"/></MultiBinding></TextBlock.Text></TextBlock>
Common Converters
BoolToVisibilityConverter
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;}}
NullToVisibilityConverter
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;}}
InverseBoolConverter
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;}}
File Structure
{Project}/└── Converters/├── ConverterMarkupExtension.cs # Base class├── MultiConverterMarkupExtension.cs # Multi base class├── BoolToVisibilityConverter.cs├── NullToVisibilityConverter.cs└── $0Converter.cs
GlobalUsings.cs
Append these to the project's existing GlobalUsings.cs (do not create a second one — duplicate global using directives fail to compile):
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;
Comparison: StaticResource vs MarkupExtension
| Aspect | StaticResource | MarkupExtension | |
|---|---|---|---|
| Resource declaration | Required | Not required | |
| XAML usage | {StaticResource Key} | {local:Converter} | |
| Singleton | Manual | Built-in (Lazy) | |
| Boilerplate | More | Less |
Related knowledge topics (via WpfDevPackMcp)
Fetch with WpfDevPackMcp get_wpf_topic:
using-converter-markup-extension— detailed MarkupExtension pattern (the canonical converter pattern)advanced-data-binding— MultiBinding patterns
Plugin rule: wpf-rule-converter-patterns skill — MarkupExtension singleton, null/UnsetValue handling, TemplateBinding guidance.