Fre*_*and 5 wpf xaml findancestor
我有两组文本块,其中一些是在itemcontrol中,其中一些不是,我想制作一个样式(仅基于类型),如果其祖先是ItemControl,则设置文本块的背景.
我可以通过以下代码来实现,但问题是在日志(和输出窗口)上将显示数据替换错误消息,因为没有Itemcontrol作为ancestore的文本块.有没有更好的方法来执行此任务并避免此错误消息?
<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>
Run Code Online (Sandbox Code Playgroud)
转换器:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
System.Windows.Data错误:4:无法找到绑定源,引用'RelativeSource FindAncestor,AncestorType ='System.Windows.Controls.ItemsControl',AncestorLevel ='1''.BindingExpression:路径=; 的DataItem = NULL; target元素是'TextBlock'(Name =''); target属性是'NoTarget'(类型'对象')
根据@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>
Run Code Online (Sandbox Code Playgroud)
转换器:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
用于查找特定类型的父级的帮助程序类:
注意:此帮助程序在逻辑或可视树中查找任何类型的父级。例如,在我的例子中,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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2680 次 |
| 最近记录: |