无法获取WPF元素的父级?

时间:2015-08-20 19:04:13

标签: c# wpf

我的WPF应用程序中有一些XAML如下:

<ListView ItemsSource="{Binding}">
    <ListView.View>
        <GridView>
            <GridViewColumn Width="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource myconverter}}">...

myconverter内,Convert()方法,代码:

    private static readonly PropertyInfo InheritanceContextProp = typeof(DependencyObject).GetProperty("InheritanceContext", BindingFlags.NonPublic | BindingFlags.Instance);

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        //the following does not work (parent returns null)
        var gvc1 = (value as GridViewColumn);
        var parent = InheritanceContextProp.GetValue(gvc1, null) as DependencyObject;

        //the following works (parent is not null)
        var gv = new GridView();
        var gvc2 = new GridViewColumn();
        gv.Columns.Add(gvc2);
        parent = InheritanceContextProp.GetValue(gvc2, null) as DependencyObject;

        return 0;
    }

我尝试在LogicalTreeHelper.GetParent()上使用VisualTreeHelper.GetParent()gvc1,但这些都不起作用(返回null或抛出异常)。

任何人都可以解释发生了什么,为什么第二个例子有效?

1 个答案:

答案 0 :(得分:0)

一个非常老的问题,但是我偶然遇到了这个问题,并且我有一个理论可以解释问题。

考虑在解析XAML时XAML处理器如何构建控件。向下浏览文件,它将创建一个ListView,创建一个GridView,然后将ListView.View属性设置为该新的GridView对象。意识到,它必须完成创建GridView才能分配该属性。

现在进入<GridViewColumn ...行。它必须先完成创建GridViewColumn,然后才能将其添加到GridView.Columns属性中。在解析行(创建GridViewColumn)时,它遇到Width="{Binding ...,并且必须评估绑定,这意味着还必须评估转换器。

因此,转换器在解析/创建GridViewColumn之前被调用, 实际上是添加到GridView中的,这解释了为什么它是“无父的”。

>

这说明了为什么第二个代码块起作用,即使第一个代码块不起作用。您要等到Columns.Add之后再致电InheritanceContextProp.GetValue

您可以通过将以下代码添加到转换器中来进一步测试:

Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
    var gvc1 = (value as GridViewColumn);
    var parent = InheritanceContextProp.GetValue(gvc1, null) as DependencyObject;
}));

这将在WPF完成加载所有内容之后运行代码 。如果您设置了断点,那么您已经等待了,您会看到parent的设置确实正确。当然,这对于实际使用转换器没有帮助,但确实说明了为什么不起作用。