15

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

4

2 に答える 2

28

問題は、がステータスをItemContainerGenerator通知するときContainersGenerated、コンテナー (a 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;
    ...
}
于 2013-07-27T06:15:36.247 に答える
-1

Caliburn.Micro を使用している場合は、これが役に立ちます。Viewmodel の場合、基本クラスは Screen である必要があり、VisualTreeHelper.GetChildrenCount() のみが no.of childs を提供します (Screen はすべての子をアクティブ化するため)

またはそれ以外の場合 (FrameworkElement)YourParent).ApplyTemplate() メソッド

于 2017-01-18T08:56:39.920 に答える