.net 参照父控件的类型设置DataTrigger的样式
在我的窗口中有几个GroupBox控件,每个控件都包含一个网格控件。对于这些网格,我想指定一种样式。但仅对直接位于GroupBox中的网格,所有其他网格都不应受到影响 我尝试了以下方法,但由于GetType()不是属性,因此该方法不起作用.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
<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。这将只查看直接父级。我的眼睛看任何祖先。