我有 2 组TextBlocks
其中一些在ItemControl
中,有些不在。
我想制作一种样式(仅基于类型),如果它的祖先是ItemControl
,则设置TextBlock
的背景。
我可以使用以下代码执行此操作,但我的问题是在日志(和输出窗口)上显示数据竞速错误消息,因为TextBlocks
没有ItemControl
作为其祖先。
有没有更好的方法来执行此任务并避免此错误消息?
<Grid>
<Grid.Resources>
<local:HasAncestorConverter x:Key="HasAncestorConverter" />
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type ItemsControl}},
Converter={StaticResource HasAncestorConverter}}" Value="True">
<Setter Property="Background"
Value="{Binding Tag,
RelativeSource={RelativeSource
AncestorType={x:Type ItemsControl}}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<StackPanel>
<TextBlock Text="Out of ItemControl" />
<ItemsControl Tag="Blue" >
<TextBlock Text="Inside of ItemControl" />
</ItemsControl>
</StackPanel>
</Grid>
变换 器:
class HasAncestorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return value != null;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
错误信息:
System.Windows.Data 错误: 4 : 找不到引用"RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1'"进行绑定的源。绑定表达式:路径=;数据项=空;目标元素是"文本块"(名称=");目标属性为"无目标"(类型为"对象")
根据@makc的回答,我以这种方式解决了问题:
<Grid>
<Grid.Resources>
<local:HasAncestorConverter x:Key="HasAncestorConverter" />
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type ItemsControl}},
Converter={StaticResource HasAncestorConverter}}" Value="True">
<Setter Property="Background"
Value="{Binding Tag,
RelativeSource={RelativeSource
AncestorType={x:Type ItemsControl}}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<StackPanel>
<TextBlock Text="Out of ItemControl" />
<ItemsControl Tag="Blue" >
<TextBlock Text="Inside of ItemControl" />
</ItemsControl>
</StackPanel>
</Grid>
转炉:
class HasAncestorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter
, System.Globalization.CultureInfo culture)
{
object parent = null;
if (value != null && parameter != null &&
parameter is Type && value is DependencyObject)
{
var control = value as DependencyObject;
Type t = parameter as Type;
parent = ParentFinder.FindParent(control, t);
}
return parent != null;
}
public object ConvertBack(object value, Type targetType, object parameter
, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
用于查找特定类型父级的辅助类:
注意:此帮助程序在逻辑或可视化树中查找任何类型的父项。例如,在我的例子中,ItemsControl
是逻辑树中的父级,它可以是祖父级。
class ParentFinder
{
public static object FindParent(DependencyObject child, Type parentType)
{
object parent = null;
var logicalParent = LogicalTreeHelper.GetParent(child);
var visualParent = VisualTreeHelper.GetParent(child);
if (!(logicalParent == null && visualParent == null))
{
if (logicalParent != null && logicalParent.GetType() == parentType)
parent = logicalParent;
else if (visualParent != null && visualParent.GetType() == parentType)
parent = visualParent;
else
{
if (visualParent != null)
parent = FindParent(visualParent, parentType);
if (parent == null && logicalParent != null)
parent = FindParent(logicalParent, parentType);
}
}
return parent;
}
}
我认为@Xameli解决方案就是您真正想要的......
但是,如果您只是必须以一种风格来做到这一点,那么您可以使用这样的VisualTreeHelper
来实现它:
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Converter={StaticResource HasAncestorConverter}}" Value="True">
<Setter Property="Background"
Value="{Binding Tag,RelativeSource={RelativeSource Self}}" />
</DataTrigger>
</Style.Triggers>
转换器:
class HasAncestorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//you probably will have to look a few levels up
var parent = VisualTreeHelper.GetParent(value) as ItemsControl;
return item != null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
对 ItemsControl
中的项目使用 DataTemplate
。
<ItemsControl ....
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding }"
Background="{Binding Tag,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<sys:String>Inside of ItemControl</String>
</ItemsControl>
保留你拥有的风格,如果你需要它给其他二传手,只需删除扳机。
您可以使用 FallbackValue 或 TargetNullValue
查看此链接:
http://dontcodetired.com/blog/post/FallbackValue-TargetNullValue-StringFormat-in-Silverlight-4.aspx