From wpf-dev-pack
Provides WPF data binding patterns including MultiBinding, PriorityBinding, and IMultiValueConverter for combining values, boolean logic, fallbacks, and async loading scenarios.
How this skill is triggered — by the user, by Claude, or both
Slash command
/wpf-dev-pack:advanced-data-bindingsonnetThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`MultiBinding` is used to combine multiple source values into a single binding target.
MultiBinding is used to combine multiple source values into a single binding target.
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
public sealed class FullNameConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length < 2 ||
values[0] is not string firstName ||
values[1] is not string lastName)
{
return DependencyProperty.UnsetValue;
}
return $"{firstName} {lastName}";
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource FullNameConverter}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
public sealed class AllTrueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values.All(v => v is true);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
<!-- Enable button only when all conditions are true -->
<Button Content="Submit">
<Button.IsEnabled>
<MultiBinding Converter="{StaticResource AllTrueConverter}">
<Binding Path="IsFormValid"/>
<Binding Path="IsNotBusy"/>
<Binding Path="HasPermission"/>
</MultiBinding>
</Button.IsEnabled>
</Button>
PriorityBinding uses the first successful value among multiple bindings. Useful for async data loading.
<TextBlock>
<TextBlock.Text>
<PriorityBinding>
<!-- Priority 1: Data loaded from server (async) -->
<Binding Path="ServerData" IsAsync="True"/>
<!-- Priority 2: Cached data -->
<Binding Path="CachedData"/>
<!-- Priority 3: Default value -->
<Binding Source="Loading..."/>
</PriorityBinding>
</TextBlock.Text>
</TextBlock>
<Image>
<Image.Source>
<PriorityBinding>
<!-- Priority 1: Original image -->
<Binding Path="HighResImage" IsAsync="True"/>
<!-- Priority 2: Thumbnail -->
<Binding Path="Thumbnail"/>
<!-- Priority 3: Default image -->
<Binding Source="/Assets/placeholder.png"/>
</PriorityBinding>
</Image.Source>
</Image>
public sealed class ConverterChain : List<IValueConverter>, IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return this.Aggregate(value, (current, converter) =>
converter.Convert(current, targetType, parameter, culture));
}
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
<local:ConverterChain x:Key="NullToVisibilityInverted">
<local:NullToBoolConverter/>
<local:InverseBoolConverter/>
<BooleanToVisibilityConverter/>
</local:ConverterChain>
public sealed class ComparisonConverter : IValueConverter
{
public ComparisonType Type { get; set; } = ComparisonType.Equal;
public object? CompareTo { get; set; }
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
var compareValue = parameter ?? CompareTo;
return Type switch
{
ComparisonType.Equal => Equals(value, compareValue),
ComparisonType.NotEqual => !Equals(value, compareValue),
ComparisonType.GreaterThan when value is IComparable c => c.CompareTo(compareValue) > 0,
ComparisonType.LessThan when value is IComparable c => c.CompareTo(compareValue) < 0,
_ => false
};
}
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
public enum ComparisonType { Equal, NotEqual, GreaterThan, LessThan }
<Window xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase">
<TextBlock Text="{Binding Path=Name,
diag:PresentationTraceSources.TraceLevel=High}"/>
</Window>
public sealed class DebugConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
System.Diagnostics.Debugger.Break();
return value;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
System.Diagnostics.Debugger.Break();
return value;
}
}
| Scenario | Recommended Pattern |
|---|---|
| Combining multiple values | MultiBinding + IMultiValueConverter |
| Async + fallback | PriorityBinding |
| Simple string format | StringFormat |
| Complex transformation | Custom IValueConverter |
| Two-way binding needed | Implement ConvertBack |
implementing-communitytoolkit-mvvm - MVVM pattern basicsmanaging-wpf-collectionview-mvvm - CollectionView bindingmapping-viewmodel-view-datatemplate - DataTemplate mappingnpx claudepluginhub christian289/dotnet-with-claudecode --plugin wpf-dev-packGenerates 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.
Guides .NET MAUI XAML data bindings including compiled bindings, value converters, binding modes, multi-binding, relative bindings, BindingContext, and MVVM with INotifyPropertyChanged.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.