如果RelativeSource不存在,则隐藏DataTrigger

时间:2011-06-08 17:04:30

标签: wpf binding

我想在我的基本TextBox样式中添加一个DataTrigger,以便它如果位于所选的DataGridCell内,则将前景颜色设置为不同的值。这是我的触发器的样子:

<Style.Triggers>
    <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridCell}}, Path=IsSelected}"
                 Value="True">
        <Setter Property="Foreground"
                Value="White" />
    </DataTrigger>
</Style.Triggers>

这很好用,除了当我的TextBox不在DataGrid中时,Binding失败并将异常写入输出窗口。我怎么能阻止这个。

我基本上想说,如果Parent是DataGridCell,则应用此触发器,否则忽略它。

1 个答案:

答案 0 :(得分:5)

一般情况下,只应用适用的样式。如果您希望隐式应用程序使用嵌套样式:

<Style TargetType="{x:Type DataGrid}">
    <Style.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <DataTrigger
                        Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridCell}}, Path=IsSelected}"
                        Value="True">
                    <Setter Property="Foreground" Value="White" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Style.Resources>
</Style>

如果您要将其他部分应用于所有TextBox,请以serarate样式取出这些部分,并使用适用于DataGrid内TextBox的样式中的BasedOn


编辑:如果不满足条件,MultiDataTrigger似乎会立即返回,因此您可以避免绑定错误:

<Style TargetType="{x:Type TextBox}">
    <Style.Resources>
        <vc:HasAncestorOfTypeConverter x:Key="HasAncestorOfTypeConverter" AncestorType="{x:Type DataGridCell}" />
    </Style.Resources>
    <Style.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition
                        Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource HasAncestorOfTypeConverter}}"
                        Value="True" />
                <Condition
                        Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridCell}}, Path=IsSelected}"
                        Value="True" />
            </MultiDataTrigger.Conditions>
            <Setter Property="Foreground" Value="Red" />
        </MultiDataTrigger>
    </Style.Triggers>
</Style>
public class HasAncestorOfTypeConverter : IValueConverter
{
    public Type AncestorType { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null) return false;
        DependencyObject current = value as DependencyObject;
        while (true)
        {
            current = VisualTreeHelper.GetParent(current);
            if (current == null)
            {
                return false;
            }
            if (current.GetType() == AncestorType)
            {
                return true;
            }
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

这当然会导致相当大的开销,所以它可能不是一个很好的解决方案,然后再次如果RelativeSource绑定失败,它也必须首先上升。