In SQL I can do this:
在SQL中我可以这样做:
Select Coalesce(Property1, Property2, Property3, 'All Null') as Value
From MyTable
If Property1, 2 and 3 are all null, then I get 'All Null'
如果Property1,2和3都为null,那么我得到'All Null'
How do I do this in XAML? I tried the following, but no luck:
我如何在XAML中执行此操作?我试过以下,但没有运气:
<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'
结果应该是'Hello World',而是'All Null'
I hope my question is clear.
我希望我的问题很清楚。
3 个解决方案
#1
7
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.
您必须构建一个自定义IMultiValueConverter才能执行此操作并使用MultiBinding。 PriorityBinding使用集合中的第一个绑定成功生成值。在您的情况下,Property1绑定立即解析,因此使用它。由于Property1为null,因此使用TargetNullValue。
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:
和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>
#2
2
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.
由于绑定到String,因此null是PriorityBinding的有效值。我不确定您的Item类的属性类型是什么,但如果您使用Object,并将它们设置为DependencyProperty.UnsetValue,您将获得您正在寻找的行为。
The PriorityBinding documentation's remarks section describes how it works in more detail.
PriorityBinding文档的备注部分更详细地描述了它的工作原理。
#3
0
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.
PriorityBinding仅查找DependencyProperty.UnsetValue以进入下一个Binding。由于Property1存在,因此设置它并且PriorityBinding将获取它的值。
For a pure XAML solution, this Style
will do the job:
对于纯XAML解决方案,此Style将完成以下任务:
<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.
虽然,这有点令人费解,但恕我直言,不属于UI,而是属于ViewModel。
#1
7
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.
您必须构建一个自定义IMultiValueConverter才能执行此操作并使用MultiBinding。 PriorityBinding使用集合中的第一个绑定成功生成值。在您的情况下,Property1绑定立即解析,因此使用它。由于Property1为null,因此使用TargetNullValue。
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:
和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>
#2
2
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.
由于绑定到String,因此null是PriorityBinding的有效值。我不确定您的Item类的属性类型是什么,但如果您使用Object,并将它们设置为DependencyProperty.UnsetValue,您将获得您正在寻找的行为。
The PriorityBinding documentation's remarks section describes how it works in more detail.
PriorityBinding文档的备注部分更详细地描述了它的工作原理。
#3
0
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.
PriorityBinding仅查找DependencyProperty.UnsetValue以进入下一个Binding。由于Property1存在,因此设置它并且PriorityBinding将获取它的值。
For a pure XAML solution, this Style
will do the job:
对于纯XAML解决方案,此Style将完成以下任务:
<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.
虽然,这有点令人费解,但恕我直言,不属于UI,而是属于ViewModel。