0

我是 WPF 新手,正在尝试使用树视图创建树。

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

根据一些在线教程,我做了以下树: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;
    }

但是由于缺乏对 WPF 的了解,我不知道应该传递给该方法的 ItemCollection 是什么。

任何建议或教程将不胜感激。

假期愉快

4

1 回答 1

0

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

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

现在您可以像这样在代码隐藏中访问此树视图的项目:

ItemCollection myDataItems = MyAwesomeTreeView.Items
GetSelectedCheckBoxes(myDataItems, MyAwesomeTreeView);

但是,您展示的方法不适用于带有数据模板的 TreeView。原因是 TreeView 只会在 TreeViewItems 在屏幕上真正可见时才生成它们。在那之前,它只包含基础数据。要解决这个问题,您需要使用 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;
}

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

于 2012-11-22T01:30:34.877 回答