关于wpftreeview的一个问题

关于wpftreeview的一个问题,wpf,Wpf,我是WPF新手,正在尝试使用treeview创建树 我想做的是动态生成一棵树。每个treeViewItem都包含一个组合框和一个文本块。当用户展开节点时,应用程序将从数据源检索子节点信息。最后,用户可以使用复选框选择几个节点 在一些在线教程之后,我做了如下树:e,如下所示: <Window.Resources> <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="Heade

我是WPF新手,正在尝试使用treeview创建树

我想做的是动态生成一棵树。每个treeViewItem都包含一个组合框和一个文本块。当用户展开节点时,应用程序将从数据源检索子节点信息。最后,用户可以使用复选框选择几个节点

在一些在线教程之后,我做了如下树:e,如下所示:

<Window.Resources>
    <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="HeaderTemplate">
            <Setter.Value>
                <HierarchicalDataTemplate DataType="{x:Type sotc:TaxNode}" ItemsSource="{Binding Path=Children}">
                    <StackPanel Orientation="Horizontal">
                        <CheckBox Name="chk" Margin="2" Tag="{Binding}"/>
                        <TextBlock Text="{Binding Path=TaxID}" ToolTip="{Binding Path=Lineage}" />
                    </StackPanel>
                </HierarchicalDataTemplate>
            </Setter.Value>
        </Setter>

    </Style>
</Window.Resources>

<Grid>
    <TreeView Margin="25,186,22,46">
        <TreeViewItem Header="Taxonomy Tree" x:Name="_TaxTree" x:FieldModifier="private">
            <TreeViewItem Header="Loading..." TextBlock.FontStyle="Italic"></TreeViewItem>
        </TreeViewItem>
    </TreeView>
</Grid>

我有一个方法来获取所选的组合框

private List<CheckBox> GetSelectedCheckBoxes(ItemCollection items)
    {
        var list = new List<CheckBox>();
        foreach (TreeViewItem item in items)
        {
            UIElement element = GetChildControl(item, "chk");
            if (element != null)
            {
                var chk = (CheckBox)element;
                if (chk.IsChecked.HasValue && chk.IsChecked.Value)
                {
                    list.Add(chk);
                }
            }

            List<CheckBox> l = GetSelectedCheckBoxes(item.Items);
            list = list.Concat(l).ToList();
        }

        return list;
    }

    private UIElement GetChildControl(DependencyObject parentObject, string childName)
    {
        UIElement element = null;
        if (parentObject != null)
        {
            int totalChild = VisualTreeHelper.GetChildrenCount(parentObject);
            for (int i = 0; i < totalChild; i++)
            {
                DependencyObject childObject = VisualTreeHelper.GetChild(parentObject, i);

                if (childObject is FrameworkElement &&
                    ((FrameworkElement)childObject).Name == childName)
                {
                    element = childObject as UIElement;
                    break;
                }

                // get its child
                element = GetChildControl(childObject, childName);
                if (element != null) break;
            }
        }

        return element;
    }
private List getselected复选框(ItemCollection项)
{
var list=新列表();
foreach(项目中的TreeView项目)
{
UIElement=GetChildControl(项目“chk”);
if(元素!=null)
{
var chk=(复选框)元素;
if(chk.IsChecked.HasValue&&chk.IsChecked.Value)
{
列表。添加(chk);
}
}
列表l=GetSelectedCheckBox(item.Items);
list=list.Concat(l.ToList();
}
退货清单;
}
私有UIElement GetChildControl(DependencyObject父对象,字符串childName)
{
UIElement=null;
if(parentObject!=null)
{
int totalChild=VisualTreeHelper.GetChildrenCount(父对象);
for(int i=0;i
但是由于缺乏关于WPF的知识,我不知道应该传递给该方法的ItemCollection是什么

如有任何建议或指导,将不胜感激


祝您假期愉快

在XAML中,您可以向TreeView添加Name属性:

<Grid>
    <TreeView Name="MyAwesomeTreeView" Margin="25,186,22,46">
        <TreeViewItem Header="Taxonomy Tree" x:Name="_TaxTree" x:FieldModifier="private">
            <TreeViewItem Header="Loading..." TextBlock.FontStyle="Italic"></TreeViewItem>
        </TreeViewItem>
    </TreeView>
</Grid>
但是,您所展示的方法在带有数据模板的TreeView上不起作用。原因是TreeView只会在TreeView项在屏幕上实际可见时生成它们。在此之前,它只包含底层数据。要解决这个问题,您需要使用TreeView的ItemContainerGenerator。将复选框方法修改为:

private List<CheckBox> GetSelectedCheckBoxes(ItemCollection items, ItemsControl source)
{
    var list = new List<CheckBox>();
    foreach (object dataitem in items)
    {
        UIElement treeviewitem = source.ItemContainerGenerator.ContainerFromItem(dataitem)
        UIElement element = GetChildControl(treeviewitem, "chk");
        if (element != null)
        {
            var chk = (CheckBox)element;
            if (chk.IsChecked.HasValue && chk.IsChecked.Value)
            {
                list.Add(chk);
            }
        }

        List<CheckBox> l = GetSelectedCheckBoxes(item.Items, treeviewitem);
        list = list.Concat(l).ToList();
    }

    return list;
}
private List getselected复选框(ItemCollection项、ItemsControl源)
{
var list=新列表();
foreach(items中的对象dataitem)
{
UIElement treeviewitem=source.ItemContainerGenerator.ContainerFromItem(dataitem)
UIElement=GetChildControl(treevieItem,“chk”);
if(元素!=null)
{
var chk=(复选框)元素;
if(chk.IsChecked.HasValue&&chk.IsChecked.Value)
{
列表。添加(chk);
}
}
列表l=GetSelectedCheckBox(item.Items,treeviewitem);
list=list.Concat(l.ToList();
}
退货清单;
}

但我想强调,这不是一种好的做事方式。我敢打赌,您试图实现的目标可以通过更简单、直接和可维护的方式实现,因此我建议您首先解释一下它是什么。

谢谢您的建议。我添加了name属性,该属性运行时出现错误:{“无法将类型为'RNAMotiveDescriptorGeneratorWPF.TaxNode'的对象强制转换为类型为'System.Windows.Controls.TreeViewItem'。”。有什么建议吗?对不起,我没有仔细阅读你的原始代码。Items属性仅返回在XAML中声明的TreeViews的TreeViewItems集合,不使用ItemsSource和HiearchicalDataTemplate。我编辑了我的答案。非常感谢你的详细解释。在“List l=GetSelectedCheckBox(item.Items,treeviewitem);”中,item.Items是什么?这是对同一方法的递归调用。这是因为TreeView是一个层次结构,这意味着如果您希望查找所有复选框,则需要在根元素下查找所有复选框,然后在根元素下的每个元素下查找所有复选框等等。。。TreeView和TreeView项都派生自wpf类ItemsControl:此类具有属性Items,该属性返回所有子元素的集合。对于数据绑定的ItemsControl,它返回ViewModels;对于手动键入的ItemsControl,它返回UIElements。
private List<CheckBox> GetSelectedCheckBoxes(ItemCollection items, ItemsControl source)
{
    var list = new List<CheckBox>();
    foreach (object dataitem in items)
    {
        UIElement treeviewitem = source.ItemContainerGenerator.ContainerFromItem(dataitem)
        UIElement element = GetChildControl(treeviewitem, "chk");
        if (element != null)
        {
            var chk = (CheckBox)element;
            if (chk.IsChecked.HasValue && chk.IsChecked.Value)
            {
                list.Add(chk);
            }
        }

        List<CheckBox> l = GetSelectedCheckBoxes(item.Items, treeviewitem);
        list = list.Concat(l).ToList();
    }

    return list;
}