Equivalent. to Coalesce () in a XAML binding?

In SQL, I can do this:

Select Coalesce(Property1, Property2, Property3, 'All Null') as Value From MyTable 

If Property1, 2, and 3 are null, then I get "All Null"

How to do this in XAML? I tried the following but no luck:

 <Window.Resources> <local:Item x:Key="MyData" Property1="{x:Null}" Property2="{x:Null}" Property3="Hello World" /> </Window.Resources> <TextBlock DataContext="{StaticResource MyData}"> <TextBlock.Text> <PriorityBinding TargetNullValue="All Null"> <Binding Path="Property1" /> <Binding Path="Property2" /> <Binding Path="Property3" /> </PriorityBinding> </TextBlock.Text> </TextBlock> 

The result should be "Hello World", but instead it is "All Null"

Hope my question is clear.

+4
data-binding wpf xaml coalesce targetnullvalue
source share
3 answers

You will need to create a custom IMultiValueConverter for this and use MultiBinding. PriorityBinding uses the first binding in the collection that successfully creates the value. In your case, the binding of Property1 is immediately resolved, so it is used. Since Property1 is null, TargetNullValue is used.

A converter like this:

 public class CoalesceConverter : System.Windows.Data.IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (values == null) return null; foreach (var item in values) if (item != null) return item; return null; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } 

And MultiBinding:

 <Window.Resources> <local:Item x:Key="MyData" Property1="{x:Null}" Property2="{x:Null}" Property3="Hello World" /> <local:CoalesceConverter x:Key="MyConverter" /> </Window.Resources> <TextBlock DataContext="{StaticResource MyData}"> <TextBlock.Text> <MultiBinding Converter="{StaticResource MyConverter}"> <Binding Path="Property1" /> <Binding Path="Property2" /> <Binding Path="Property3" /> </MultiBinding> </TextBlock.Text> </TextBlock> 
+7
source share

Since you are binding to String , null is a valid value for PriorityBinding . I'm not sure what the property types of your Item class are, but if you use Object and set them to DependencyProperty.UnsetValue , you will get the behavior you are looking for.

The PriorityBinding notes section describes how this works in more detail.

+2
source share

PriorityBinding searches for DependencyProperty.UnsetValue only to go to the next Binding . Since Property1 exists, it is set, and PriorityBinding takes a value.

For a clean XAML solution, this Style will do the job:

  <TextBlock> <TextBlock.Style> <Style TargetType="{x:Type TextBlock}"> <Setter Property="Text" Value="{Binding Property1}" /> <Style.Triggers> <DataTrigger Binding="{Binding Property1}" Value="{x:Null}"> <Setter Property="Text" Value="{Binding Property2}" /> </DataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding Property1}" Value="{x:Null}" /> <Condition Binding="{Binding Property2}" Value="{x:Null}" /> </MultiDataTrigger.Conditions> <Setter Property="Text" Value="{Binding Property3}" /> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding Property1}" Value="{x:Null}" /> <Condition Binding="{Binding Property2}" Value="{x:Null}" /> <Condition Binding="{Binding Property3}" Value="{x:Null}" /> </MultiDataTrigger.Conditions> <Setter Property="Text" Value="All Null" /> </MultiDataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock> 

Although this is a slightly confusing way to do this, and IMHO does not belong in the user interface, but in the ViewModel.

0
source share

All Articles