ItemsControl.ItemContainerGenerator.ContainerFromItem()返回null?

时间:2017-01-23 08:32:59

标签: c# wpf xaml

我有一些奇怪的行为,我似乎无法解决。当我遍历ItemsControl.ItemsSource属性中的项目时,我似乎无法获得容器?我希望看到一个Button返回,但我只能得到null。

有什么想法吗?

<!-- MyWindow.xaml -->
    <Window 
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Window1" Height="300" Width="300" Foreground="White" Name="mainPanel">

        <ItemsControl x:Name="ItemsControl_1" Margin="20">
        <!-- ItemsPanelTemplate -->
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Columns="2" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <!-- ItemTemplate -->
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Content="{Binding Path=Prop_1}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

    </Window>

我的代码无效。返回null

    public static void StartWindow()
            {

                // MyWindow
                System.Windows.Window win;
                // Load MyWindow
                using (FileStream fs = new FileStream(@"C:\MyWindow.xaml", FileMode.Open))
                {
                    object obj = System.Windows.Markup.XamlReader.Load(fs);
                    win = (System.Windows.Window)obj;
                }

                //This code set ItemsSource
                foreach (DependencyObject fe in FindLogicalChildren<DependencyObject>(win))
                {
                    ItemsControl itemscontrol = fe as ItemsControl;
                    if (fe is ItemsControl)
                    {
                        itemscontrol.ItemsSource = new List<My_Class>() { 
                            new My_Class("Button1"), 
                            new My_Class("Button2"), 
                            new My_Class("Button3") };

                    }
                }
         // This  code get ItemsSource<DependencyObject>
                foreach (DependencyObject fe in FindLogicalChildren<DependencyObject>(win))
                {

                    if (fe is ItemsControl)
                    {
                        ItemsControl itemsControl = fe as ItemsControl;
                        itemsControl.UpdateLayout();
                        for (int i = 0; i < itemsControl.Items.Count; i++)
                        {
                            DependencyObject c = (DependencyObject)itemsControl.ItemContainerGenerator.ContainerFromIndex(i);
                            **//This code return NULL !!!**
                            if (c != null)
                                Display.MsgBox(c.GetType().Name);
                            else
                                Display.MsgBox("NULL");
                        }
                    }
                }
                win.ShowDialog();

            }


public class My_Class
{
    public string Prop_1 { get; set; }

    public My_Class(string prop1)
    {
        Prop_1 = prop1;
    }
}

            public static IEnumerable<T> FindLogicalChildren<T>(DependencyObject depObj) where T : DependencyObject
            {
                if (depObj != null)
                {
                    foreach (object rawChild in LogicalTreeHelper.GetChildren(depObj))
                    {
                        if (rawChild is DependencyObject)
                        {
                            DependencyObject child = (DependencyObject)rawChild;
                            if (child is T)
                            {
                                yield return (T)child;
                            }

                            foreach (T childOfChild in FindLogicalChildren<T>(child))
                            {
                                yield return childOfChild;
                            }
                        }
                    }
                }
            }

窗口已加载

enter image description here

1 个答案:

答案 0 :(得分:2)

ContainerFromIndex方法将返回ContentPresenter。您可以像这样获得对Button的引用:

ItemsControl itemsControl = ItemsControl_1;
for (int i = 0; i<itemsControl.Items.Count; i++)
{
    ContentPresenter cp = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as ContentPresenter;
    if (cp != null && VisualTreeHelper.GetChildrenCount(cp) > 0)
    {
        Button button = VisualTreeHelper.GetChild(cp, 0) as Button;
        //...
    }
}

编辑您还应该等到窗口加载并且在您尝试访问它们之前实际创建了容器:

public static void StartWindow()
{
    // MyWindow
    System.Windows.Window win;
    // Load MyWindow
    using (FileStream fs = new FileStream(@"C:\MyWindow.xaml", FileMode.Open))
    {
        object obj = System.Windows.Markup.XamlReader.Load(fs);
        win = (System.Windows.Window)obj;
    }

    win.Loaded += (ss, ee) => 
    {
        //access the containers here...
    };

    win.ShowDialog();
}