Search code examples
wpfsilverlighttreeviewtreeviewitem

How do you determine the width of the text in a WPF TreeViewItem at run time?


How do you determine the width of the text in a WPF TreeViewItem at run time?

I need to calculate an offset so I can draw a line from one leaf to the leaf of a different TreeView. All the 'width' properties return a size that is way bigger than the space taken up by the actual text of the node. It must be possible because the Select feature doesn't highlight the entire row. I'm writing the client in WPF and Silverlight.


Solution

  • I have two solutions:

    A) Uses the visual tree

        TreeViewItem selected = (TreeViewItem)dataSourceTreeView.SelectedItem;
        double textWidth = 0;
        double expanderWidth = 0;
        Grid grid = (Grid)VisualTreeHelper.GetChild(selected, 0);
    
        ToggleButton toggleButton = (ToggleButton)VisualTreeHelper.GetChild(grid, 0);
        expanderWidth = toggleButton.ActualWidth;
    
        Border bd = (Border)VisualTreeHelper.GetChild(grid, 1);
        textWidth = bd.ActualWidth;
    

    B) If you don't want to use the visual tree

        TreeViewItem selected = (TreeViewItem)dataSourceTreeView.SelectedItem;
        double textWidth = 0;
        Typeface typeface = new Typeface(selected.FontFamily,
            selected.FontStyle, selected.FontWeight, selected.FontStretch);
    
        GlyphTypeface glyphTypeface;
        if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
                throw new InvalidOperationException("No glyphtypeface found");
    
        string headerText = (string)selected.Header;
        double size = selected.FontSize;
    
        ushort[] glyphIndexes = new ushort[headerText.Length];
        double[] advanceWidths = new double[headerText.Length];
    
        for (int n = 0; n < headerText.Length; n++)
        {
                ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[headerText[n]];
                glyphIndexes[n] = glyphIndex;
    
                double width = glyphTypeface.AdvanceWidths[glyphIndex] * size;
                advanceWidths[n] = width;
    
                textWidth += width;
        }