.net 参照父控件的类型设置DataTrigger的样式

.net 参照父控件的类型设置DataTrigger的样式,.net,wpf,xaml,binding,styles,.net,Wpf,Xaml,Binding,Styles,在我的窗口中有几个GroupBox控件,每个控件都包含一个网格控件。对于这些网格,我想指定一种样式。但仅对直接位于GroupBox中的网格,所有其他网格都不应受到影响 我尝试了以下方法,但由于GetType()不是属性,因此该方法不起作用 <Style TargetType="Grid"> <Style.Triggers> <DataTrigger Binding="{Binding RelativeSource={RelativeSourc

在我的窗口中有几个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>

我已经找到了一个解决方案,但这并不是一个很好的解决方案,因为我必须修改GroupBox:

<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>

显然,我可以手动设置每个网格的样式,但我试图避免这种情况,因为有很多网格。我希望您能找到一种方法使第一个示例生效。


<DataTrigger Binding="{Binding Path=Parent.Tag, RelativeSource={RelativeSource Mode=Self}}" Value="blub">
这段代码不起作用,因为模式的类型实际上是BindingMode,它是一个枚举,并且它的任何成员都不是Self。因此,这个赋值模式=Self在代码中是错误的。要了解模式的可能值

写这篇文章的正确方法是

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

当然,为了让它工作,你必须保持你已经写过的GroupBox的风格

使用以下代码:

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>

这对我很有用:

        <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>


它允许您根据父类型设置样式,而不必求助于代码而不是标记真正应该使用的标记。

恐怕您错了。我的代码运行得很好。模式不是BindingMode类型,而是RelativeSourceMode类型。我的猜测是您忽略了RelativeSource={RelativeSource Mode=Self}中的大括号,它使模式成为RelativeSource的属性,而不是绑定的属性。@Peter:您是对的。这种水平滚动让我感到不安,我并没有真正注意到内部大括号使RelativeSource的
模式
属性。谢谢你指出错误!:-)这看起来很有希望。我发现有趣的是,(CLR)类型仅通过GetType()方法可用,而DependencyObjectType(AFAIK基本上是CLR类型的包装器)是一个属性。是的,我发现它也很有趣。我还研究了为什么GetType是一个方法而不是一个属性。有各种各样的观点,包括效率、滥用、关于一个财产获取者应该做什么的惯例等等。我没有机会去测试它。您能告诉我以下触发器定义是否等效吗?(我的想法行得通吗?)我的原始想法:
您的版本:
我没有太多WPF/xaml经验,所以请对此持保留态度:您的指定路径=Parent.DependencyObjectType.Name。这将只查看直接父级。我的眼睛看任何祖先。