WpfMart 1.0.1

dotnet add package WpfMart --version 1.0.1                
NuGet\Install-Package WpfMart -Version 1.0.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="WpfMart" Version="1.0.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add WpfMart --version 1.0.1                
#r "nuget: WpfMart, 1.0.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install WpfMart as a Cake Addin
#addin nuget:?package=WpfMart&version=1.0.1

// Install WpfMart as a Cake Tool
#tool nuget:?package=WpfMart&version=1.0.1                

WpfMart

A set of WPF helpers and utilities such as value converters, markup-extensions, behaviors, etc.

GitHub Source Code Repo.
WpfMart NuGet Package.

Table of content


Markup-extensions

Casting markup-extension

WpfMart.Markup.CastExtension WpfMart.Markup.IntExtension WpfMart.Markup.DoubleExtension WpfMart.Markup.LongExtension WpfMart.Markup.LongExtension WpfMart.Markup.DateTimeExtension WpfMart.Markup.TimeSpanExtension WpfMart.Markup.CharExtension WpfMart.Markup.BoolExtension

Provides type conversion to the specified type, mainly from a string written in XAML. Used as shorthand for writing values of primitive type in XAML in places the expected type is System.Object.

Please note that it's not necessary to do any casting when assigning to a Property of the desired type.


<ComboBox SelectedIndex="1" />

<ComboBox SelectedIndex="{z:Int 1}" />

<ComboBox Tag="{z:Int 1}" />

<ComboBox Tag="1" />

The CastExtension is used by specifying its target type either through constructor or its ToType property.

Whenever possible use the more specific cast markups such as BoolExtension, IntExtension, DoubleExtension, etc. instead of the general purpose CastExtension


<Control><Control.Tag><sys:Int32>-1</sys:Int32></Control.Tag></Control>

<Control Tag="{z:Int -1}" />


<ContentControl><ContentControl.Content><sys:Double>0.5</sys:Double></ContentControl.Content></ContentControl>

<ContentControl Content="{z:Double 0.5}" />



<ContentControl><ContentControl.Content><sysio:SeekOrigin>-1</sysio:SeekOrigin></ContentControl.Content></ContentControl>

<ContentControl Content="{z:Cast -1, sysio:SeekOrigin}" />

<ContentControl Content="{z:Cast en-us, globalization:CultureInfo}" />

EnumValues markup-extension

WpfMart.Markup.EnumValuesExtension

Provides Enum's values for the provided Enum type.

<ComboBox ItemsSource="{z:EnumValues sysio:SeekOrigin}" />

Simplify the ability to get enum values as ItemsSource.

  • Some values can be excluded from the list by specifying them using the Exclude property as comma delimited names or numbers. <ComboBox ItemsSource="{z:EnumValues globalization:GregorianCalendarTypes, Exclude=11,22}" />
  • Can also extract the enum value names as string, int number of description of DescriptionAttribute, by setting the Mode property. <ComboBox ItemsSource="{z:EnumValues globalization:GregorianCalendarTypes, Mode=Name}" />
  • Can provide a value-converter to perform conversion of the results, using the Converter property
enum MachineStateEnum
{
    None,
    [Description("Wax On")]
    On,
    [Description("Wax Off")]
    Off,
    [Description("Wax Burn")]
    Faulted
}

<ComboBox ItemsSource="{z:EnumValues local:MachineStateEnum}" />


<ComboBox ItemsSource="{z:EnumValues local:MachineStateEnum, Exclude=None,Faulted}" />
<ComboBox ItemsSource="{z:EnumValues local:MachineStateEnum, Exclude=0,2}" />


<ComboBox ItemsSource="{z:EnumValues local:MachineStateEnum, Mode=Number}" />

<ComboBox ItemsSource="{z:EnumValues local:MachineStateEnum, Mode=Description}" />


<ComboBox ItemsSource="{z:EnumValues local:MachineStateEnum, Converter={myconv:EnumToStringResourceConverter}" />
<ComboBox ItemsSource="{z:EnumValues local:MachineStateEnum, Converter={myconv:EnumToReadableStringConverter}" />
<ComboBox ItemsSource="{z:EnumValues local:MachineStateEnum, Mode=Name, Converter={myconv:ToUpperCaseConverter}" />

Value Converters

GroupConverter

WpfMart.Converters.GroupConverter

Groups several value-converters together.

Performs Convert from top to bottom converter and ConvertBack from bottom to top converter. If one of the converter's return value is either Binding.DoNothing or DependencyProperty.UnsetValue, the conversion stop. When converting back, if one of the converter implement interface ICantConvertBack, it's skipped from conversion

<Control.Resources>
    
    <conv:GroupConverter x:Key="IsMotorCurrentInRangeConverter">
      <conv:NumInRangeConverter From="10" To="20" TrueValue="{x:Null}" FalseValue="{conv:UseInputValue}" />
      <conv:NumInRangeConverter From="-20" To="-10" NullValue="{x:Static conv:Boxed.True}" />
    </conv:GroupConverter>
    
    
    <conv:GroupConverter x:Key="NullSafeNumberToGregorianCalendarTypes">
        <conv:CastConverter ToType="glob:GregorianCalendarTypes" />
        <conv:TargetNullValueConverter Value="{x:Static glob:GregorianCalendarTypes.Localized}" />
        <conv:InRangeConverter From="{x:Static glob:GregorianCalendarTypes.Localized}"
                               To="{x:Static glob:GregorianCalendarTypes.Arabic}" 
                               TrueValue="{conv:UseInputValue}", 
                               FalseValue="{x:Static glob:GregorianCalendarTypes.Localized}" />
    </conv:GroupConverter>
</Control.Resources>
<ContentControl Content="{Binding NullableInt, Converter={StaticResouces NullSafeNumberToGregorianCalendarTypes}" />
<CheckBox IsEnabled="{Binding MeasuredElectricCurrent, Converter={StaticResource IsMotorCurrentInRangeConverter}}" />

BoolConverter

WpfMart.Converters.BoolConverter
Converts a bool or nullable bool value to another value specified by properties TrueValue, FalseFalue and NullValue.

<Control.Resources>
 
 <conv:BoolConverter x:Key="BoolToOnOffConverter" TrueValue="On" FalseValue="Off" />
                           
 
 <conv:BoolConverter x:Key="IsTrueToMachineStateEnum" 
                     TrueValue="{x:Static local:MachineState.On}"
                     FalseValue="{x:Static local:MachineState.Off}" />
</Control.Resources>                     

Nullable bool

In order to support nullable bool, either set NullValue property to a desired value to return when converting a null value or set IsNullable to true and by that, NullValue property will have its default value of null.
(which is same as setting NullValue property to {x:Null}. )

if none of the above properties are set, null is not converted and considered as false.
Consider using the Binding's TargetNullValue instead.

<CheckBox IsThreeState="True" IsChecked="{Binding IsChecked, Converter={conv:BoolConverter IsNullable=True}}" />
<ComboBox SelectedItem="{Binding IsMachineOn, Converter={conv:BoolConverter 
            TrueValue={x:Static local:MachineState.On}
            FalseValue={x:Static local:MachineState.Off}
            NullValue={x:Static local:MachineState.None}}}" />
IsNegative

Converter can be negative, meaning comparing to false instead of true, by setting IsNegative property to true.
Although, for that purpose there is a predefined converter:

NegativeBoolConverter

WpfMart.Converters.NegativeBoolConverterExtension

<CheckBox x:Name= IsThreeState="True" Content="{Binding IsKnownToBeClosed, Converter={conv:NegativeBoolConverter IsNullable=True}}" />

<ContentControl Content="{Binding IsOff, Converter={StaticResource IsTrueToMachineStateEnum}, ConverterParameter=True}" />
Reverse conversion

There is ability to switch between Convert and ConvertBack, by setting IsReversed property to True.
It will check if converted value equals to TrueValue property and return true otherwise false.
If null is supported, it's also compared to NullValue property and returns null if equals.

enum MachineState { None, On, Off }
<Control.Resources>
   
   <conv:BoolConverter x:Key="EnumToIsCheckedConverter" 
                       IsReversed="True"
                       TrueValue="{x:Static local:MachineState.On}" 
                       FalseValue="{x:Static local:MachineState.Off}"
                       NullValue="{x:Static local:MachineState.None}" />
</Control.Resources>
<StackPanel>
    <ComboBox x:Name="combobox" ItemsSource="{z:EnumValues local:MachineState}" SelectedIndex="0" />
    <CheckBox IsThreeState="True" 
              IsChecked="{Binding SelectedItem, ElementName=combobox, Converter={StaticResource EnumToIsCheckedConverter}}"/>
</StackPanel>

BoolToVisibilityConverter

WpfMart.Converters.BoolToVisibilityConverter
The difference between this converter and built-in WPF converter System.Windows.Data.BooleanToVisibilityConverter
Is that with this converter has additional abilities as follow:

Hidden instead of Collapsed

it's possible to use Visibility.Hidden instead of Visibility.Collapsed

<Border x:Name="ContentPlaceHolder" Visibility="{Binding IsMissings, Converter={conv:BoolToVisibilityConverter UseHidden=True}}" />
IsNegative

Converter can be negative, meaning comparing to false instead of true, by setting IsNegative property to true.

Another way to look at it is, return Visibility.Visible when converting from false,
otherwise Visibility.Collapsed (or Visibility.Hidden if UseHidden property is true)

<TextBlock Visibility="{Binding HasLicense, Converter={conv:BoolToVisibilityConverter IsNegative=True}}">
    <Hyperlink NavigateUri="http://www.url.com/license" >Acquire license here...</Hyperlink>
</TextBlock>
IsReversed

There is ability to switch between Convert and ConvertBack, by setting IsReversed property to True.
It will check if converted value equals to Visibility.Visible and then return true, otherwise false.
(Unless IsNegative property is true, and therefore the conversion is opposite)

<StackPanel>
    <ContentControl x:Name="MovieDetailsViewPlaceHolder" />
    
    <TextBox Text="{Binding EditorComments}"
        IsEnabled="{Binding Content.Visibility, ElementName=MovieDetailsViewPlaceHolder,
            Converter={conv:BoolToVisibilityConverter IsRevered=True}}"/>
</StackPanel>

There are predefined converters of BoolToVisibilityConverter, that are configured to common needs, such as:

TrueToCollapsedConverter

WpfMart.Converters.TrueToCollapsedConverterExtension
Converts from true to Visibility.Collapsed, otherwise to Visibility.Visible

<TextBlock Visibility="{Binding HasLicense, Converter={conv:TrueToCollapsedConverter}}">
    <Hyperlink NavigateUri="http://www.url.com/license" >Acquire license here...</Hyperlink>
</TextBlock>
TrueToHiddenConverter

WpfMart.Converters.TrueToHiddenConverterExtension
Converts from true to Visibility.Hidden, otherwise to Visibility.Visible

<Border x:Name="ContentPlaceHolder" Visibility="{Binding IsMissings, Converter={conv:TrueToHiddenConverter}}" />
FalseToHiddenConverter

WpfMart.Converters.FalseToHiddenConverterxtension
Converts from false to Visibility.Hidden, otherwise to Visibility.Visible


Converter special values

In some of the converters, where it has a property that can be set to any object,
i.e. BoolConverter.TrueValue, BoolConverter.FalseValue, EqualityComparer.CompareTo
It's possible to provide special values from WpfMart.Converters.ConverterSpecialValue class
That will affect the desired behavior of the converter.

<conv:BoolConverter TrueValue="{x:Static conv:ConverterSpecialValue.UseConverterParameter}" />

For each of the special values there is also a corresponding markup-extension that is simpler to use than the {x:Static} syntax.
The special values are:

  • UseInputValue - {conv:UseInputValue}
    Indicates that the converter should use the 'value' parameter passed to the Convert method.
  • UseConverterParameter - {conv:UseConverterParameter}
    Indicates that the converter should use the ConverterParameter value used in Binding.ConverterParameter to the Convert method.
  • ThrowException - {conv:ThrowException}
    Indicates that the converter should throw System.InvalidOperationException.
    Used only as rare option to cause exception in case developer requires that certain conditions won't go unnoticed.
    Such as to trigger the System.Windows.Data.Binding.ValidatesOnExceptions property.
<Control.Resources>
  <conv:EqualityConverter x:Key="CompareToParameterReturnBackground" 
                          CompareTo="{conv:UseConverterParameter}" 
                          TrueValue="Green", FalseValue="Red" />
</Control.Resources>
<TextBlock Text="On" 
  Background="{Binding MachineState, 
    Converter={StaticResource CompareToParameterReturnBackground}, 
    ConverterParameter={x:Static local:MachineState.On}}}" />
<TextBlock Text="Off" 
  Background="{Binding MachineState, 
    Converter={StaticResource CompareToParameterReturnBackground}, 
    ConverterParameter={x:Static local:MachineState.Off}}}" />   

<TextBox Text="{Binding Name, ValidatesOnExceptions=True,
         Converter={conv:EqualityConverter TrueValue={conv:ThrowException}, FalseValue={conv:UseInputValue}}}" />

Please note that the built-in WPF special values such as:
DependencyProperty.UnsetValue, Binding.DoNothing are still valid.
but now they got markup-extension to make it simpler to use from XAML:
{conv:UnsetValue}, {conv:DoNothing}


<conv:EqualityConverter x:Key="CompareToParameterReturnBackground" 
                          CompareTo="{conv:UseConverterParameter}" 
                          TrueValue="Green", FalseValue="{Conv:UnsetValue}" />

CastConverter

Converts a value to another type

The difference between CastConverter and CastExtension is that CastConverter.ProvideValue returns IValueConverter,
while CastExtension performs the conversion and returns the value after conversion.

<ComboBox SelectedItem="{Binding MachineStateNumber, Converter={conv:CastConverter ToType={x:Type local:MachineState}}" />

In order to be able to convert-back, the ConvertBackToType property should be set.

<ComboBox SelectedItem="{Binding MachineStateNumber, 
            Converter={conv:CastConverter ToType={x:Type local:MachineState}, ConvertBackToType={x:Type sys:Int32}}" />
Chaining converters

When used as markup-extension it's possible to chain another converter to convert from.
using the FromConverter property as follow:


<TextBlock Text="{Binding NullableMachineStateId,
    Converter={conv:CastConverter {x:Type local:MachineState},
    FromConverter={conv:EqualityConverter TrueValue={z:Int 0}, FalseValue={conv:UseInputValue}}}" />

the chaining ability apply most of the value-converters in the package.
This ability should not be abused. use it intelligently, in most of the cases a single converter can do the job.
When not used with markup-extension syntax, wrap with GroupConverter to chain several converters.

enum MachineState { None, On, Off }
<Control.Resources>
    <conv:GroupConverter x:Key="NullSafeNumberToMachineStateEnum">
        <conv:TargetNullValueConverter Value="{z:Int 0}" />
        <conv:CastConverter ToType="{x:Type local:MachineState}" />
    </conv:GroupConverter>
</Control.Resources>

<TextBlock Text="{Binding NullableMachineStateId, Converter={StaticResource NullSafeNumberToMachineStateEnum}}" />

EqualityConverter

WpfMart.Converters.EqualityConverter
Checks if converted value equals to the value of CompareTo property,
if equals, return value of TrueValue property, otherwise FalseValue property.

<CheckBox IsChecked="{Binding SeekOrigin, CompareTo={x:Static sysio:SeekOrigin.Current}}" />
enum MachineState { None, On, Off }
<ComboBox SelectedItem="{Binding MachineState, Converter={conv:EqualityConverter
            CompareTo={x:Static local:MachineState.None}
            TrueValue={x:Null}
            FalseValue={conv:UseInputValue}}}">
    <x:Static Member="local:MachineState.On" />
    <x:Static Member="local:MachineState.Off" />
</ComboBox>

If the CompareTo property is not set, then by default it's null and therefore the converter can be used to check for null value.

<CheckBox Content="Use default" IsChecked="{Binding SelectedItem, Converter={conv:EqualityConverter}}" />

IsNegative

Converter can be negative, meaning checking if the value is not equals to the CompareTo property,
by setting IsNegative property to true.


<ComboBox SelectedIndex="0"
    IsEnabled="{Binding Items.Count, RelativeSource={RelativeSource Self}, 
        Converter={conv:EqualityConverter IsNegative=True, CompareTo={z:Int 0}}}"   />

null value

In order to additionally handle conversion from a null value (in addition for comparing to desired value),
either set NullValue property to a desired value to return when converting a null value,
or set IsNullable to true and by that, NullValue property will have its default value of null.
(which is same as setting NullValue property to {x:Null}. )

if none of the above properties are set, no special handling for null is done, and only comparing to CompareTo property.
Consider using the Binding's TargetNullValue instead.

Chaining converters

When used as markup-extension it's possible to chain another converter to convert from.
using the FromConverter property as follow:


<TextBlock Text="{Binding UserInput,
  Converter={conv:EqualityConverter CompareTo='YES', TrueValue='Confirmed', FalseValue='---', NullValue='invalid'
  FromConverter={notmyconv:ToUpperCaseConverter}}} />

There are predefined converters of EqualityConverter, that are configured to common needs, such as:

EqualityToVisibilityConverter

WpfMart.Converters.EqualityToVisibilityConverterExtension
Checks if converted value equals to the value of CompareTo property,
if equals, return value of Visibility.Visible, otherwise Visibility.Collapsed.

  • The converter can be negative (checking it's not equals to CompareTo property), by setting the IsNegative property to true.
  • The converter can return Visibility.Hidden instead of Visibility.Collapsed, by setting the UseHidden property to true.
IsNotNullConverter

WpfMart.Converters.IsNotNullConverterExtension
convert a null to false and non-null value to true.

NullToInvisibleConverter

WpfMart.Converters.NullToInvisibleConverterExtension
Converts a null to Visiblity.Collapsed, otherwise to Visiblity.Visible.


InRangeConverter

WpfMart.Converters.InRangeConverter
Check if value is in range of lower and/or upper bounds.
if in range, returns TrueValue property , otherwise FalseValue property.
The range of values is specified using:

  • Fromproperty, for inclusive lower bound, or After property, for exclusive lower bound.
  • To property, for inclusive upper bound, or Before property, for exclusive upper bound.

The more interesting aspect of the converter is to perform greater-than/less-than conditions
by only specifying one of the bounds (lower or upper) as follow:


<conv:InRangeConverter From="{x:Static diag:TraceLevel.Error}" />

<conv:InRangeConverter After="{x:Static diag:TraceLevel.Error}" />

<conv:InRangeConverter To="{x:Static diag:TraceLevel.Info}" />

<conv:InRangeConverter Before="{x:Static diag:TraceLevel.Info}" />

<TextBlock 
  Visibility="{Binding TraceLevel, Converter={conv:InRangeConverter 
                From={x:Static diag:TraceLevel.Info},
                TrueValue=Visible, FalseValue=Collapsed}}"
  Text="Note: Log file might contain too many entries and get over sized" />

Some notes:

  • Avoid setting upper to be less than or equals to the lower bound, as the converter won't function as expected.
  • In case setting same value for lower and upper bound, it's same as comparing to a specific value, therefore prefer using EqualityConverter converter instead.

IsNegative

Converter can be negative, meaning checking if the value is not in range,
by setting IsNegative property to true.

Note: null value is considered out of range.

enum CustomerType { Regular, Repeating, Loyal, Vip, OurEmployee }
<Window.Resources>
  
  <conv:InRangeConverter x:Key="IsNotPreferredCustomer" IsNegative="True"
                         From="{x:Static local:CustomerType.Repeating}"
                         To="{x:Static local:CustomerType.Vip}" />
</Window.Resources>
<TextBox Text="{Binding PromoCode}" IsReadOnly="{Binding CustomerType, Converter={StaticResource IsNotPreferredCustomer}}"/>

null value

In order to specially handle conversion from a null value,
either set NullValue property to a desired value to return when converting a null value,
or set IsNullable to true and by that, NullValue property will have its default value of null.
(which is same as setting NullValue property to {x:Null}. )

if none of the above properties are set, no special handling for null is done and it's considered not in range,
but resulting value depends on the IsNegative property.
Consider using the Binding's TargetNullValue instead.

In order to specify range value of numeric types of date-time, it's possible to use the CastExtension parts,
such as {z:Int}, {z:Double}, {z:DateTime}, etc...
But, there are predefined InRangeConverterconverters configured for common usages such as that:

NumInRangeConverter

WpfMart.Converters.NumInRangeConverter
A InRangeConverter that used numeric values as lower/upper bounds.
It From,After,To,Before properties are of type Decimal.


<ComboBox ItemsSource="{Binding Users}" SelectedIndex="0"
  IsEnabled="{Binding Items, RelativeSource={RelativeSource Self}, Converter={conv:NumInRangeConverter From=2}}" />

<TextBlock Text="Angle will be fixed to value between 0 to 360 (not including)"
    Visibility="{Binding Angle, Converter={conv:NumInRangeConverter From=0, Before=360, TrueValue=Collapsed, FalseValue=Visible}}"/>
DateInRangeConverter

WpfMart.Converters.NumInRangeConverter
A InRangeConverter that used DateTime values as lower/upper bounds.

It's advised to specify the dates is xaml in universal format: 'yyyy-MM-dd'


<TextBlock Text="Windows XP updates are only available after October 25, 2001 and before April 8, 2014"
    Visibility="{Binding OSVersionDate, Converter={conv:DateInRangeConverter 
        After=2001-10-25, Before=2014-04-8, TrueValue=Collapsed, FalseValue=Visible}}" />
Chaining converters

When used as markup-extension it's possible to chain another converter to convert from.
using the FromConverter property as follow:


<TextBlock Text="{Binding KeyCode}"
  Background="{Binding KeyCode, Converter={conv:InRangeConverter From=1, Before=a,
                NullValue=LightYellow, TrueValue=LightGreen, FalseValue=Coral,
                FromConverter={conv:NullOrEmptyConverter TrueValue={x:Null}, FalseValue={conv:UseInputValue}}}" />
Recap examples
enum CustomerType { Regular, Repeating, Loyal, VIP, OurEmployee}

<ListBox HorizontalContentAlignment="Stretch">
  <CheckBox IsChecked="{Binding RedeemPreferredCustomerDiscount}" Content="Redeem valuable customer 5% discount"
            Visibility="{Binding CustomerType, Converter={conv:InRangeConverter 
                          From={x:Static local:CustomerType.Loyal}, 
                          To={x:Static local:CustomerType.VIP},
                          TrueValue=Visible, FalseValue=Collapsed}}" />
            
  <TextBlock Text="Coupon code:" />
    
  <TextBox Text="{Binding CouponCode, UpdateSourceTrigger=PropertyChanged}"
           Background="{Binding CouponCode, Converter={conv:InRangeConverter NullValue={conv:UnsetValue},
                          From=1, Before=a, TrueValue={conv:UnsetValue}, FalseValue=Coral,
                          FromConverter={conv:NullOrEmptyConverter TrueValue={x:Null}, FalseValue={conv:UseInputValue}}}}" />
</ListBox>


MapConverter

WpfMart.Converters.MapConverter
Converts a key to a mapped value.

Defines a dictionary of key-value pairs for which a converted value is considered a key in the dictionary
and the matching value for the key is returned as result.
The dictionary is defined in the same manner as a ResourceDictionary is defined in XAML.

<Window.Resources>
  
  <conv:MapConverter x:Key="SeekOriginToIcon">
    <BitmapImage x:Key="{x:Static sysio:SeekOrigin.Begin}" UriSource="../Assets/SeekBegin.png" />
    <BitmapImage x:Key="{x:Static sysio:SeekOrigin.Current}" UriSource="../Assets/SeekCurrent.png" />
    <BitmapImage x:Key="{x:Static sysio:SeekOrigin.End}" UriSource="../Assets/SeekEnd.png" />
  </conv:MapConverter>
</Window.Resources>
<Button Command="{Binding SeekToCommand}" >
  <Image Source="{Binding SelectedSeekOrigin, Converter={StaticResource SeekOriginToIcon}}" />
</Button>

In case the key not found in the dictionary, there will be an attempt to located by its ToString() value.
This in order to make it more flexible to specify some keys in XAML.
(Illustration on the above example)

  <conv:MapConverter x:Key="SeekOriginToIcon">
    <BitmapImage x:Key="Begin" UriSource="../Assets/SeekBegin.png" />
    <BitmapImage x:Key="Current" UriSource="../Assets/SeekCurrent.png" />
    <BitmapImage x:Key="End" UriSource="../Assets/SeekEnd.png" />
  </conv:MapConverter>

Fallback value

If the key couldn't be found in the dictionary, a fallback-value is used,
by setting the desired value in the FallbackValue property.
by default it will return the key itself, which is actually the input value to be converted.

<Window.Resources>
  
  <conv:MapConverter x:Key="GregorianCalendarTypesToText" FallbackValue="-----">
    <sys:String x:Key="{x:Static glob:GregorianCalendarTypes.Localized}" >Local</sys:String>
    <sys:String x:Key="{x:Static glob:GregorianCalendarTypes.USEnglish}" >English</sys:String>
    <sys:String x:Key="{x:Static glob:GregorianCalendarTypes.Arabic}"    >Arabic</sys:String>
  </conv:MapConverter>
</Window.Resources>
<TextBlock Text="{Binding SelectedCalendarType, Converter={StaticResource GregorianCalendarTypesToText}}" />

null value

In order to map a null to a value, it's not possible to set it as a key in a dictionary.
<conv:MapConverter><sys:String x:Key={x:Null}>No value</sys:String></conv:MapConverter>
For this purpose use the NullValue property to set the value to return when converting from null.

Consider using the Binding's TargetNullValue instead.

enum MachineState { None, On, Off, Faulted, Maintenance }
<Window.Resources>
  <SolidColorBrush x:Key="GrayBrush" Color="Gray" />
  <conv:MapConverter x:Key="MachineStateToBackground" NullValue="{StaticResource GrayBrush}" FallbackValue="{conv:UnsetValue}" >
    <SolidColorBrush x:Key="{x:Static local:MachineState.On}" Color="Green" />
    <SolidColorBrush x:Key="{x:Static local:MachineState.Off}" Color="Red" />
    <SolidColorBrush x:Key="{x:Static local:MachineState.Faulted}" Color="Orange" />
  </conv:MapConverter>
</Window.Resources>

Converting back

The MapConverter also performs convert-back.
To specify a fallback value in case convert-back cannot find value in the dictionary,
use the ConvertBackFallbackValue property. by default it cancel the conversion (Binding.DoNothing).

in case more than one key mapped to the same value,
The resulting key from convert-back can be any of them.

Mapping to another converter

If a mapped value in the dictionary is a value-converter, by default it will be used in order to produce the final value.
to disable this ability, set ConvertAlsoFoundValueConverter property to false.
Also be aware that performing convert-back won't work if involving embedded value-converter.


<conv:MapConverter x:Key="AngleToNameOrRoundedAngle" FallbackValue="{conv:CastConverter ToType={x:Type sys:Int32}}" >
  <sys:String x:Key="{z:Double 0.0}"  >Zero</sys:String>
  <sys:String x:Key="{z:Double 90.0}" >Ninty</sys:String>
  <sys:String x:Key="{z:Double 180.0}">One hundred eighty</sys:String>
</conv:MapConverter>
<TextBlock Text="{Binding Angle, Converter={StaticResource AngleToNameOrRoundedAngle}}" />

Recap Examples

enum MachineState { None, On, Off, Faulted, Maintenance }
<Window.Resources>
    
   <conv:MapConverter x:Key="MachineStateToIsChecked" FallbackValue="{x:Null}" 
                      ConvertBackFallbackValue="{x:Static local:MachineState.None}" >
        <sys:Boolean x:Key="{x:Static local:MachineState.On}" >True</sys:Boolean>
        <sys:Boolean x:Key="{x:Static local:MachineState.Off}" >False</sys:Boolean>
    </conv:MapConverter>
    
     
    <conv:MapConverter x:Key="MachineStateToForeground" FallbackValue="{conv:UnsetValue}">
        <SolidColorBrush x:Key="{x:Static local:MachineState.On}" Color="Green" />
        <SolidColorBrush x:Key="{x:Static local:MachineState.Off}" Color="Red" />
        <SolidColorBrush x:Key="{x:Static local:MachineState.Faulted}" Color="Orange" />
    </conv:MapConverter>

     
    <conv:MapConverter x:Key="ForegroundToTextConverter" NullValue="{x:Null}" >
        <sys:String x:Key="#FF008000" >Green</sys:String>
        <sys:String x:Key="#FFFF0000" >Red</sys:String>
        <sys:String x:Key="#FFFFA500" >Orange</sys:String>

        <conv:MapConverter.FallbackValue>
            <Rectangle Width = "50" Height="2" StrokeThickness="2" Stroke="Blue" StrokeDashArray="1,2,1,2" Margin="1,7" />
        </conv:MapConverter.FallbackValue>
    </conv:MapConverter>
 </Window.Resources>
 
 <CheckBox x:Name="MachineStateToThreeStateCheck" IsThreeState="True"
   IsChecked="{Binding MachineState, Converter={StaticResource MachineStateToIsChecked}}"
   Content="{Binding Foreground, RelativeSource={RelativeSource Self}, Mode=OneWay, 
                     Converter={StaticResource ForegroundToTextConverter}}"
   Foreground="{Binding MachineState, Mode=OneWay, Converter={StaticResource MachineStateToForeground}}" />

NullOrEmptyConverter

WpfMart.Converters.NullOrEmptyConverter
Checks if converted value is either null or empty string or empty collection (IEnumerable),
if equals, return value of TrueValue property, otherwise FalseValue property.


<TextBlock IsEnabled="{Binding DevicesList, Converter={conv:NullOrEmptyConverter}}">
    <Hyperlink NavigateUri="http://www.url.com/license" >Scan devices...</Hyperlink>
</TextBlock>
<Border BorderBrush="{Binding Username, Converter={conv:NullOrEmptyConverter TrueValue=Orange, FalseValue=Green}}" BorderThickness="2">
  <TextBox Text="{Binding Username}" />
</Border>

In order to check only for empty string/collection, change the Mode property from IsNullOrEmpty (default) to IsEmpty.
<conv:NullOrEmptyConverter Mode=IsEmpty />

IsNegative

Converter can be negative, and check if the value is neither null nor empty string/collection,
by setting IsNegative property to true.


<ComboBox SelectedIndex="0"
    IsEnabled="{Binding Items, RelativeSource={RelativeSource Self}, 
        Converter={conv:NullOrEmptyConverter IsNegative=True}}"   />

There are predefined converters of NullOrEmptyConverter, that are configured to common needs, such as:

IsNotNullOrEmptyConverter

WpfMart.Converters.IsNotNullOrEmptyConverterExtension
Convert a null or empty string/collection to false, otherwise to true.


<ComboBox SelectedIndex="0"
    IsEnabled="{Binding Items, RelativeSource={RelativeSource Self}, Converter={conv:IsNotNullOrEmptyConverter}}" />
NullOrEmptyToInvisibleConverter

WpfMart.Converters.NullOrEmptyToInvisibleConverterExtension
Convert a null or empty string/collection to Visibility.Collapsed, otherwise Visibility.Visible.


<ComboBox SelectedIndex="0"
    Visibility="{Binding Items, RelativeSource={RelativeSource Self}, Converter={conv:NullOrEmptyToInvisibleConverter}}" />

Chaining converters

This converter also has the ability to chain another converter to convert from.
using the FromConverter property. (see previous examples).


Multi Value Converters

EqualityMultiConverter

WpfMart.Converters.EqualityMultiConverter
Checks equality of two values provided by bindings.
(The array of values passed to the converter's Convert method contains the two values)
if equals, return value of TrueValue property, otherwise FalseValue property.

<CheckBox IsEnabled="False" Content="Reached max attempts">
  <CheckBox.IsChecked>
    <MultiBinding Converter="{conv:EqualityMultiConverter}" >
      <Binding Path="RetryCount" />
      <Binding Path="MaxRetries" />
    </MultiBinding>
  </CheckBox.IsChecked>
</CheckBox>
<StackPanel>
  <ComboBox x:Name="SaladDressing1" ItemsSource="{Binding AvailableSaladDressing}"/>
  <ComboBox x:Name="SaladDressing2" ItemsSource="{Binding AvailableSaladDressing}" />
  
  <TextBlock Text="Please notice you picked the same salad dressing for both options" >
    <TextBlock.Visibility>
      <MultiBinding Converter="{conv:EqualityMultiConverter TrueValue=Collapsed, FalseValue=Visible}" >
        <Binding Path="SelectedItem" ElementName="SaladDressing1" TargetNullValue="DiffFromOption2" />
        <Binding Path="SelectedItem" ElementName="SaladDressing2" TargetNullValue="DiffFromOption1" />
      </MultiBinding>
    </TextBlock.Visibility>
  </TextBlock>
</StackPanel>

IsNegative

Converter can be negative, meaning checking if values are not equals to each other,
by setting IsNegative property to true.

<TextBox Text="{Binding CouponCode}" >
  <TextBox.IsReadOnly>
    <MultiBinding Converter="{conv:EqualityMultiConverter IsNegative=True}" >
      <Binding Path="CouponsUsedsoFar" />
      <Binding Path="MaxCouponsAllowed" />
    </MultiBinding>
  </TextBox.IsReadOnly>
</TextBox>

InRangeMultiConverter

WpfMart.Converters.InRangeMultiConverter
Check if value is in range of lower and/or upper bounds.
if in range, returns TrueValue property , otherwise FalseValue property.

The array of values passed to the converter's Convert method is treated as follow:

  • The value to check if in range - values[0]
  • By default values[1] is the lower bound of the range and values[2] is the upper bound of the range.

The converter is very similar to InRangeConverter
except that the lower/upper bounds are provided using Binding inside a MultiBinding.

<TextBlock Text="{Binding MeasuredValue}" >
  <TextBlock.Background>
    <MultiBinding Converter="{conv:InRangeMultiConverter TrueValue=Green, FalseValue=Red}">
      <Binding Path="MeasuredValue" />
      <Binding Path="MinAllowedValue" />
      <Binding Path="MaxAllowedValue" />
    </MultiBinding>
  </TextBlock.Background>
</TextBlock>

To specify if lower/upper bounds are inclusive or exclusive,
set properties LowerInclusive and/or UpperInclusive to true or false.
By default the bounds are inclusive.

<TextBlock Text="{Binding MeasuredValue}" >
  <TextBlock.Background>
    <MultiBinding Converter="{conv:InRangeMultiConverter LowerInclusive=False,  UpperInclusive=False, TrueValue=Green, FalseValue=Red}">
      <Binding Path="MeasuredValue" />
      <Binding Path="LowerOutOfRangeValue" />
      <Binding Path="UpperOutOfRangeValue" />
    </MultiBinding>
  </TextBlock.Background>
</TextBlock>

The more interesting aspect of the converter is to perform greater-than/less-than conditions
by only specifying one of the bounds (lower or upper) by binding to only a value and a single limit,
and in addition set only one of the properties LowerInclusive or UpperInclusive to indicate which limit to use.
(otherwise it defaults to lower inclusive).

<CheckBox Content="Passed the test" IsEnabled="False">
  <CheckBox.IsChecked>
    <MultiBinding Converter="{conv:InRangeMultiConverter LowerInclusive=True}" >
      <Binding Path="Grade" /> 
      <Binding Path="MinGrade" /> 
    </MultiBinding>
  </CheckBox.IsChecked>
</CheckBox>
  • Setting only LowerInclusive to True performs Greater than or Equals to. setting to False performs Greater than.
  • Setting only UpperInclusive to True performs Less than or Equals to. setting to False performs Less than.

The above is true only if binding to 1 limit. if binding to 2 limits (see very first example),
then in-range check is done on both limits.

<StackPanel Orientation="Horizontal">
  <DatePicker x:Name="FromDatePicker" />
  <DatePicker x:Name="ToDatePicker" />
  <TextBlock Text="From date should be less than To date">
    <TextBlock.Visibility>
      <MultiBinding Converter="{conv:InRangeMultiConverter UpperInclusive=False, TrueValue=Collapsed, FalseValue=Visible}" >
        <Binding Path="SelectedDate" ElementName="FromDatePicker" /> 
        <Binding Path="SelectedDate" ElementName="ToDatePicker" /> 
      </MultiBinding>
    </TextBlock.Visibility>
  </TextBlock>
</StackPanel>

IsNegative

Converter can be negative, meaning checking if the value is not in range,
by setting IsNegative property to true.

Note: null value is considered out of range.

enum CustomerType { Regular, Repeating, Loyal, Vip, OurEmployee }
<Window.Resources>
  <conv:InRangeMultiConverter x:Key="IsRangeToVisibility" LowerInclusive="True" TrueValue="Visible", FalseValue="Collapsed" />
</Window.Resources>
<Button Content="Try again">
  <Button.Visibility>
    
    <MultiBinding Converter="{StaticResource IsRangeToVisibility}" ConverterParameter="True" >
      <Binding Path="Grade" />
      <Binding Path="MinGrade" />
    </MultiBinding>
  </Button.Visibility>
</Button>

<TextBlock Content="You passed the test">
  <TextBlock.Visibility>
    <MultiBinding Converter="{StaticResource IsRangeToVisibility}" >
      <Binding Path="Grade" />
      <Binding Path="MinGrade" />
    </MultiBinding>
  </TextBlock.Visibility>
</TextBlock>

null value

In order to specially handle conversion from a null value,
either set NullValue property to a desired value to return when converting a null value,
or set IsNullable to true and by that, NullValue property will have its default value of null.
(which is same as setting NullValue property to {x:Null}. )

if none of the above properties are set, no special handling for null is done and it's considered not in range,
but resulting value depends on the IsNegative property.
Consider using the Binding's TargetNullValue instead.


Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.1 is compatible. 
.NET Framework net452 is compatible.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETCoreApp 3.1

    • No dependencies.
  • .NETFramework 4.5.2

    • No dependencies.
  • .NETFramework 4.8

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.1 448 11/11/2022
1.0.0 384 1/8/2022