c# - ItemsControl.ItemContainerGenerator.ContainerFromItem() 返回 null?

标签 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>

我的代码无法运行。返回空

    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

最佳答案

ContainerFromIndex 方法将返回一个 ContentPresenter。您可以获得对按钮的引用,如下所示:

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

关于c# - ItemsControl.ItemContainerGenerator.ContainerFromItem() 返回 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41801974/

相关文章:

c# - 如何将文本框绑定(bind)到日期时间字段但仅显示其日期部分(在 ASP.MVC 中)?

c# - WPF TextBox MaxLength——有没有办法将其绑定(bind)到绑定(bind)字段上的数据验证最大长度?

c# - 对 Point3D 使用并行处理

c# - INotifyPropertyChanged - 数据访问、业务或 UI 层

c# - 模板控件中的 ContentPresenter 不起作用

c# - 如何在 ASP.NET Core 5 中使用 IdentityUser 和 IdentityRole 之间的隐式多对多

c# - C# 中的 Ajax 发布等效项

c# - 防止后台任务更新 LiveTile

c# - 使用 WrapPanel 添加一个 TextBox 作为 ItemsControl 的最后一个元素

wpf - 将 WPF 设计数据与 MVVM 模式一起使用