样式DataTrigger参考父控件的类型

时间:2010-11-28 19:17:26

标签: .net wpf xaml binding styles

在我的窗口上有几个GroupBox控件,每个控件包含一个网格控件。对于那些我希望设计风格的网格。但只对那些直接位于GroupBox中的网格,所有其他网格都不应受到影响。

我尝试过以下操作,但由于GetType()不属性,因此无效。

<Style TargetType="Grid">
    <Style.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Parent.GetType()}" Value="{x:Type GroupBox}">
           <!-- <Setter Property="..." Value="..."/> -->
        </DataTrigger>
    </Style.Triggers>
</Style>

我找到了一个解决方法,但它并不是一个非常漂亮的解决方案,因为我必须修改GroupBoxes:

<Style TargetType="GroupBox">
    <Setter Property="Tag" Value="blub"/>
 </Style>
<Style TargetType="Grid">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=Parent.Tag, RelativeSource={RelativeSource Mode=Self}}" Value="blub">
           <!-- <Setter Property="..." Value="..."/> -->
        </DataTrigger>
    </Style.Triggers>
</Style>

显然我可以手动设置每个Grid的样式,但我试图避免这种情况,因为它们中有很多。我希望你能找到一种让第一个例子有效的方法。

3 个答案:

答案 0 :(得分:7)

<DataTrigger Binding="{Binding Path=Parent.Tag, RelativeSource={RelativeSource Mode=Self}}" Value="blub">

这段代码不起作用,因为Mode的类型实际上是BindingMode,它是一个Enumeration,它的成员都不是Self。因此,您的代码中的 Mode = Self 分配错误。要了解模式的可能值,click this

写这个的正确方法是,

<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}, Path=Tag}" Value="blub">

当然,为了实现这一点,你必须保留你已经编写的GroupBox的Style。

答案 1 :(得分:2)

这对我有用:

        <Style.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StatusBar}}, Path=DependencyObjectType.Name}" Value="StatusBar">
                <Setter Property="Margin" Value="0"/>
                <Setter Property="Padding" Value="0"/>
                <Setter Property="Background" Value="Chartreuse"/>
            </DataTrigger>
        </Style.Triggers>

它允许您根据父类型设置样式,而不必使用Tag,它应该由代码而不是标记使用。

答案 2 :(得分:0)

使用以下代码:

using DevExpress.Xpf.Core.Native;
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace BindingErrorHelper
{
    public class IsTypeFoundConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            FrameworkElement element = value as FrameworkElement;
            Type type = parameter as Type;
            if (element != null && type != null)
            {
                element = LayoutHelper.FindElement(element,type);
                if (element != null)
                    return true;
            }
            return false;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
    }

    public class LayoutHelper
    {
        public static FrameworkElement FindElement(FrameworkElement treeRoot, Type type)
        {
        FrameworkElement parentElement = VisualTreeHelper.GetParent(treeRoot) as FrameworkElement;
        while (parentElement != null)
        {
            if (parentElement.GetType() == type)
                return parentElement;
            else
                parentElement = VisualTreeHelper.GetParent(parentElement) as FrameworkElement;
        }
        return null;
        }
    }
}

将XAML代码写为:

<tt:IsTypeFoundConverter x:Key="isTypeFoundConverter"/>

<Style TargetType="Grid">
    <Style.Triggers>
        <DataTrigger Binding={Binding RelativeSource={RelativeSource Self}, Converter={StaticResource isTypeFoundConverter}, ConverterParameter={x:Type GroupBox}}" Value="true">
           <!-- <Setter Property="..." Value="..."/> -->
        </DataTrigger>
    </Style.Triggers>
</Style>