using-converter-markup-extension

Using Converter Markup Extension

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "using-converter-markup-extension" with this command: npx skills add christian289/dotnet-with-claudecode/christian289-dotnet-with-claudecode-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+)

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

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 NotSupportedException();
}

}

Example 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;
}

}

XAML Usage:

<Button Visibility="{Binding IsEnabled, Converter={local:BoolToVisibilityConverter}}"/>

<!-- With parameter --> <Button Visibility="{Binding IsDisabled, Converter={local:BoolToVisibilityConverter}, ConverterParameter=Invert}"/>

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; } }

StringFormatConverter

public sealed class StringFormatConverter : ConverterMarkupExtension<StringFormatConverter> { public override object? Convert( object? value, Type targetType, object? parameter, CultureInfo culture) { if (parameter is not string format) return value?.ToString();

    return string.Format(culture, format, value);
}

}

XAML Usage:

<TextBlock Text="{Binding Price, Converter={local:StringFormatConverter}, ConverterParameter='{}{0:C}'}"/>

FullNameConverter (Multi)

public sealed class FullNameConverter : MultiConverterMarkupExtension<FullNameConverter> { public override object? Convert( object?[] values, Type targetType, object? parameter, CultureInfo culture) { if (values.Length < 2) return string.Empty;

    var firstName = values[0]?.ToString() ?? string.Empty;
    var lastName = values[1]?.ToString() ?? string.Empty;

    return $"{firstName} {lastName}".Trim();
}

}

XAML Usage:

<TextBlock> <TextBlock.Text> <MultiBinding Converter="{local:FullNameConverter}"> <Binding Path="FirstName"/> <Binding Path="LastName"/> </MultiBinding> </TextBlock.Text> </TextBlock>

GlobalUsings.cs

global using System; global using System.Globalization; global using System.Windows; global using System.Windows.Data; global using System.Windows.Markup;

Migration from StaticResource

Before

<Window.Resources> <local:BoolToVisibilityConverter x:Key="BoolToVisibility"/> </Window.Resources>

<Button Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisibility}}"/>

After

<!-- No resource declaration needed --> <Button Visibility="{Binding IsVisible, Converter={local:BoolToVisibilityConverter}}"/>

File Structure

MyApp/ ├── Converters/ │ ├── ConverterMarkupExtension.cs # Base class │ ├── MultiConverterMarkupExtension.cs # Multi base class │ ├── BoolToVisibilityConverter.cs │ ├── NullToVisibilityConverter.cs │ └── StringFormatConverter.cs

Checklist

  • Inherit from ConverterMarkupExtension<T> or MultiConverterMarkupExtension<T>

  • Class is sealed (no inheritance needed)

  • Handle null input gracefully

  • Return DependencyProperty.UnsetValue for invalid input if needed

  • Use ConverterParameter for variations instead of multiple converters

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

converting-html-css-to-wpf-xaml

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

publishing-wpf-apps

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

managing-styles-resourcedictionary

No summary provided by upstream source.

Repository SourceNeeds Review