关于WPF树视图的问题

时间:2012-11-21 23:46:51

标签: wpf

我是WPF的新手,并尝试使用treeview创建一个树。

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

在一些在线教程之后,我做了以下树: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是什么。

非常感谢任何建议或教程。

度过愉快的假期

1 个答案:

答案 0 :(得分:0)

在您的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>

现在,您现在可以在代码隐藏中访问此树视图中的项目,如下所示:

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

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