7

我有 2 套,TextBlocks其中一些在一个中ItemControl,而其中一些不在。

我想制作一种样式(仅基于类型),TextBlock如果它的祖先是ItemControl.

我可以使用以下代码来做到这一点,但我的问题是在日志(和输出窗口)上显示了一条数据竞价错误消息,因为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''的绑定源。绑定表达式:路径=;数据项=空;目标元素是'TextBlock'(名称='');目标属性是“NoTarget”(类型“对象”)

4

4 回答 4

3

根据@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;
    }
}
于 2013-10-29T18:25:24.690 回答
3

我认为@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();
    }
}
于 2013-10-29T14:36:44.310 回答
1

用于DataTemplate中的项目ItemsControl

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

如果您需要其他 setter 的样式,请保留您的样式,只需移除触发器即可。

于 2013-10-29T13:24:48.007 回答
0

您可以使用 FallbackValue 或 TargetNullValue

检查此链接:

http://dontcodetired.com/blog/post/FallbackValue-TargetNullValue-StringFormat-in-Silverlight-4.aspx

于 2013-10-28T21:48:56.483 回答