Help us improve
Share bugs, ideas, or general feedback.
From wpf-dev-pack
Provides WPF data binding patterns including MultiBinding, PriorityBinding, and IMultiValueConverter for combining values, boolean logic, fallbacks, and async loading scenarios.
npx claudepluginhub christian289/dotnet-with-claudecode --plugin wpf-dev-packHow 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.
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.
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.
Share bugs, ideas, or general feedback.
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 mapping