VisualTreeHelper.GetChildrenCount return 0?

I use VisualTreeHelper.GetChildrenCount() to search for child controls, but always returns 0.

Here is my code

 <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 # code:

 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 name is set for search if (frameworkElement != null && frameworkElement.Name == childName) { // if the child name is of the request name foundChild = (T)child; break; } } else { // child element found. foundChild = (T)child; break; } } return foundChild; } 

VisualTreeHelper.GetChildrenCount() always returns 0,

The code for creating the elements is here.

 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(); 

I searched the forum and the Internet, but I can’t solve it, can someone help me?

Thank you very much!

T & T

+6
source share
2 answers

The problem is that when an ItemContainerGenerator signals the status of ContainersGenerated , a container (a ContentPresenter ) has been created but not yet loaded. Especially the data template has not yet been applied to ContentPresenter, so there is nothing in the visual tree.

You can get around this by adding a Loaded event handler when navigating through the generated containers.

 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; ... } 
+23
source

If you use Caliburn.Micro, this will help you. For your view model, the base class should be "Screen", and only "VisualTreeHelper.GetChildrenCount" () should not specify child elements. (Since the screen activates all children

or otherwise (FrameworkElement) YourParent). Method ApplyTemplate ()

0
source

Source: https://habr.com/ru/post/950408/


All Articles