views:

120

answers:

1

When a node in my TreeView has multiple lines, the TreeView bullet gets vertically centered.

How can I top-align the TreeView bullet?

alt text

<pages:BasePage.Resources>
    <data:HierarchicalDataTemplate x:Key="OutlineTemplate"
        ItemsSource="{Binding OutlineDocumentObjects}">
        <TextBlock Text="{Binding Line}" 
            TextWrapping="Wrap" 
            VerticalAlignment="Top"
            Width="600"/>
    </data:HierarchicalDataTemplate>
</pages:BasePage.Resources>

<StackPanel Style="{StaticResource StackPanelPageWrapperStyle}">
    <tk:TreeView x:Name="TheTreeView" 
        ItemsSource="{Binding TheOutline.OutlineDocumentObjects}"
        ItemTemplate="{StaticResource OutlineTemplate}">
    </tk:TreeView>
</StackPanel>
+1  A: 

Good question... of course, it could be done by redefining the template, but it's a pain... (if you want to go that way, extract the template with StyleSnooper or ShowMeTheTemplate and change the VerticalAlignment of the ToggleButton)

Another way is to inherit TreeViewItem and override the OnApply method. Since the ToggleButton has a name ("Expander") in the default template, you can find it and apply the VerticalAlignment you want :

public class TopAlignedTreeViewItem : TreeViewItem
{
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        if (Template != null)
        {
            ToggleButton btn = Template.FindName("Expander", this) as ToggleButton;
            if (btn != null)
            {
                btn.VerticalAlignment = VerticalAlignment.Top;
            }
        }
    }
}

For the TreeView to generate TopAlignedTreeViewItems instead of TreeViewItems, you also need to make your own TreeView :

public class TopAlignedTreeView : TreeView
{
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return (item is TopAlignedTreeViewItem);
    }

    protected override System.Windows.DependencyObject GetContainerForItemOverride()
    {
        return new TopAlignedTreeViewItem();
    }
}
Thomas Levesque
What do I need to reference in my code behind to use Template.FindName?
Edward Tanguay
nothing, Template is a property of the current instance (this.Template)
Thomas Levesque
I'm getting: 'System.Windows.Controls.ControlTemplate' does not contain a definition for 'FindName' and no extension method 'FindName' accepting a first argument of type 'System.Windows.Controls.ControlTemplate' could be found (are you missing a using directive or an assembly reference?)
Edward Tanguay
Ah, you must be using Silverlight... Template.FindName is available only in WPF. So I guess you will have to redefine the template...
Thomas Levesque
sorry, yes, I'm using silverlight, ok, I'll go that route
Edward Tanguay