views:

39

answers:

1

In learning WPF, I (perhaps unwisely) chose to display my XML data (wisely parsed with LINQ) in a TreeView. But when I load it into a TreeView, it looks like this:

alt text

The XAML is as follows:

<TreeView Name="StoryTree">
    <TreeViewItem Name="TreeGeneral" Header="General"/>
    <TreeViewItem Name="TreeCharacters" Header="Characters" />
    <TreeViewItem Name="TreeEvents" Header="Events" />
    <TreeViewItem Name="TreeFactions" Header="Factions" />
    <TreeViewItem Name="TreeLocations" Header="Locations" />
    <TreeViewItem Name="TreePlots" Header="Plots" />
    <TreeViewItem Name="TreeReferences" Header="References" />
    <TreeViewItem Name="TreeScenes" Header="Scenes" />
</TreeView>

In the code-behind, I load the items into the treeview with a simple routine as follows:

    private void Update(StoryItem[] items, TreeViewItem parentNode)
    {
        //  Suppress updating if there are no actual changes.
        if (Changed(items, parentNode))
        {

            //  Remove all items from the child node.
            ClearItem(parentNode);

            //  Reinsert the child nodes.
            foreach (var item in items)
            {
                //  Create a TreeViewItem and insert it into the TreeView.
                //  Note that the item must support double clicking so that the 
                //  user can open the item. Also, we want to support tooltips
                //  for the items so that the summary text (if any) will display
                //  when the user hovers over the item with the mouse.
                TreeViewItem treeItem = new TreeViewItem();
                TextBlock block = new TextBlock();
                block.Text = item.Name;
                block.ToolTip = item.Summary;
                block.TextTrimming = TextTrimming.WordEllipsis;
                treeItem.Items.Add(block);
                parentNode.Items.Add(treeItem);
            }
        }
    }

I kind of suspect that this is the "cascading style inheritance" in WPF, but I'm not entirely sure (the top-level nodes look fine), but it might be something about the way I'm creating the child nodes.

DISCLAIMER: Please don't delve into talks about binding the treeview. For this particular app, the data is NEVER going to consist of more than a category header (top-level nodes) and the items immediately below them. What I want to know is why the top level nodes look fine and the ones I created are different from them.

I've tried eliminating the padding on both the TreeViewItem and the margin & padding on the TextBlock, both to no avail.

(Visual STudio 2008 SP1, .NET 3.5, Win7)

+2  A: 

I think this is because you are adding your children inside another (redundant) tree item. As that tree item only contains a single child and no header, you are getting the extra level in the tree that you need to expand.

Try the following:

        foreach (var item in items)
        {
            //  Create a TreeViewItem and insert it into the TreeView.
            //  Note that the item must support double clicking so that the 
            //  user can open the item. Also, we want to support tooltips
            //  for the items so that the summary text (if any) will display
            //  when the user hovers over the item with the mouse.

            TreeViewItem child = new TreeViewItem();
            child.Header = item.Name;
            child.ToolTip = item.Summary;

            parentNode.Items.Add(block);
        }
Steve Greatrex
I'll give that a shot. I had placed them in a treeview on the advice of Adam Nathan, author of *WPF 4 Unleashed*, who says, "Always use TreeViewItem to explicitly wrap items in a TreeView!It might be tempting to use simple TextBlocks as leaf nodes, but when you do so, you canrun into a subtle property value inheritance trap that can make the text in such TextBlocksseem to disappear. By default, selecting a parent node changes its Foreground to white,and if TextBlocks are direct logical children, their text turns white as well. [Cont'd...]
Mike Hofer
"(Although theimplicit TreeViewItem is the visual parent for each TextBlock, the logical parent takesprecedence for inheritance.) Against the default white background, such text cannot be seen.If you make TreeViewItem the explicit (logical) parent of each TextBlock, however, theundesirable inheritance no longer occurs."
Mike Hofer
...And, indeed, Adam Nathan was right. :(
Mike Hofer
I hadn't heard that before, but I have edited my answer to use a TreeViewItem with the header text set instead of containing a child TextBlock. I haven't tested this one though...
Steve Greatrex
Alternatively, you could just style the TextBlock to overwrite the default highlighting behaviour!
Steve Greatrex
But you were right! Child controls were the answer. :) Instead of creating a TextBlock, I just used a TreeViewItem, and gave up TextTrimming (oh, well).
Mike Hofer
Haven't yet dived into styling too deeply. (I just want it to *work* at this point.) I'll worry about styling this project later. Then I'll revisit this issue (it has a // TODO: tag on it) and see if I can't get text trimming back on it. It's *all* about the aesthetics, after all.
Mike Hofer
:) absolutely! As the Header property is of type `object`, you may be able to set the value to an instance of TextBlock with whatever trimming you want set on that. Again, I haven't tested this though!
Steve Greatrex