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-packThis skill uses the workspace's default tool permissions.
`MultiBinding` is used to combine multiple source values into a single binding target.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
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