In SQL I can do this:
Select Coalesce(Property1, Property2, Property3, \'All Null\') as Value
From MyTable
If Property1, 2 and 3 are all n
The PriorityBinding
is only looking for DependencyProperty.UnsetValue
to advance to the next Binding
. Since Property1
exists it is set and the PriorityBinding
is taking the value of it.
For a pure 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, it's a bit convoluted way of doing it, and IMHO, doesn't belong in the UI but in the ViewModel.
You'd have to build a custom IMultiValueConverter to do that and use a MultiBinding. PriorityBinding uses the first binding in the collection that produces a value successfully. In your case, the Property1 binding resolves immediately, so it's used. Since Property1 is null, the 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 like this:
<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>
Since you are binding to a String
, null is a valid value for the PriorityBinding
. I'm not sure what your Item class's property types are, but if you use Object
, and set them to DependencyProperty.UnsetValue
, you will get the behavior you are looking for.
The PriorityBinding documentation's remarks section describes how it works in more detail.