VisualTreeHelper.GetChildrenCount返回0?

时间:2013-07-27 05:14:54

标签: c# wpf

我正在使用VisualTreeHelper.GetChildrenCount()来查找子控件,但它总是返回0.

这是我的代码

<ScrollViewer x:Name="scrollViewerChannelsRecordTimeData">
    <StackPanel x:Name="channelsRecordTimeData">
        <ItemsControl x:Name="channelRecordTimeItems" ItemsSource="{Binding}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid x:Name="hoursLines">
                        //Some Controls here                            
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</ScrollViewer>   

C#代码:

channelRecordTimeItems.ItemContainerGenerator.StatusChanged += ChannelRecordTimeItemsStatusChangedEventHandler;
private void ChannelRecordTimeItemsStatusChangedEventHandler(Object sender, EventArgs e)
{
    if (channelRecordTimeItems.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
    {
        if (channelRecordTimeItems.HasItems)
        {
            DependencyObject dependencyObject = null;
            Grid gridHighlightRecordData = null;
            for (int i = 0; i < channelRecordTimeItems.Items.Count; i++)
            {
                dependencyObject = channelRecordTimeItems.ItemContainerGenerator.ContainerFromIndex(i); //dependencyObject != null
                 if (dependencyObject != null)
                 {
                    Grid hoursLines = FindElement.FindChild<Grid>(dependencyObject, "hoursLines"); //hoursLines = null
                 }
            }
        }
    }
}

public static T FindChild<T>(DependencyObject parent, string childName)
   where T : DependencyObject
{
    // Confirm parent and childName are valid. 
    if (parent == null) return null;

    T foundChild = null;

    int childrenCount = VisualTreeHelper.GetChildrenCount(parent); //Return 0 here
    for (int i = 0; i < childrenCount; i++)
    {
        var child = VisualTreeHelper.GetChild(parent, i);
        // If the child is not of the request child type child
        T childType = child as T;
        if (childType == null)
        {
            // recursively drill down the tree
            foundChild = FindChild<T>(child, childName);

            // If the child is found, break so we do not overwrite the found child. 
            if (foundChild != null) break;
        }
        else if (!string.IsNullOrEmpty(childName))
        {
            var frameworkElement = child as FrameworkElement;
            // If the child's name is set for search
            if (frameworkElement != null && frameworkElement.Name == childName)
            {
                // if the child's name is of the request name
                foundChild = (T)child;
                break;
            }
        }
        else
        {
            // child element found.
            foundChild = (T)child;
            break;
        }
    }

    return foundChild;
}

VisualTreeHelper.GetChildrenCount()始终返回0,

此处构建项目的代码

List<ChannelRecordTimeItemData> listChannelRecordTimeItemData = new List<ChannelRecordTimeItemData>();
for(int i = 0; i < 5; i++)
{
    ChannelRecordTimeItemData item = new ChannelRecordTimeItemData();
    listChannelRecordTimeItemData.Add(ChannelRecordTimeItemData);
}
channelRecordTimeItems.ItemsSource = listChannelRecordTimeItemData;
channelRecordTimeItems.Items.Refresh();

我在论坛和互联网上搜索过,但我无法解决,有人可以帮助我吗?

非常感谢!

T&amp; T公司

2 个答案:

答案 0 :(得分:25)

问题是,当ItemContainerGenerator发出ContainersGenerated状态信号时,容器(ContentPresenter)已创建但尚未加载。特别是数据模板尚未应用于ContentPresenter,因此可视树中没有任何内容。

您可以通过在生成的容器上循环时添加Loaded事件处理程序来解决此问题。

private void ItemContainerGeneratorStatusChanged(object sender, EventArgs e)
{
    if (itemsControl.ItemContainerGenerator.Status
        == GeneratorStatus.ContainersGenerated)
    {
        var containers = itemsControl.Items.Cast<object>().Select(
            item => (FrameworkElement)itemsControl
                .ItemContainerGenerator.ContainerFromItem(item));

        foreach (var container in containers)
        {
            container.Loaded += ItemContainerLoaded;
        }
    }
}

private void ItemContainerLoaded(object sender, RoutedEventArgs e)
{
    var element = (FrameworkElement)sender;
    element.Loaded -= ItemContainerLoaded;

    var grid = VisualTreeHelper.GetChild(element, 0) as Grid;
    ...
}

答案 1 :(得分:-1)

如果您使用Caliburn.Micro,这将对您有所帮助。 对于您的Viewmodel,基类应该是Screen,然后只有VisualTreeHelper.GetChildrenCount()给出no.of childs。(因为Screen将激活所有子项

或 否则(FrameworkElement)YourParent).ApplyTemplate()方法