make-wpf-converter — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited make-wpf-converter (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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 multiCreate 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.csAppend 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;| Aspect | StaticResource | MarkupExtension |
|---|---|---|
| Resource declaration | Required | Not required |
| XAML usage | {StaticResource Key} | {local:Converter} |
| Singleton | Manual | Built-in (Lazy) |
| Boilerplate | More | Less |
Fetch with WpfDevPackMcp get_wpf_topic:
using-converter-markup-extension — detailed MarkupExtension pattern (the canonical converter pattern)advanced-data-binding — MultiBinding patternsPlugin rule: wpf-rule-converter-patterns skill — MarkupExtension singleton, null/UnsetValue handling, TemplateBinding guidance.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.