I have the following piece of XAML that creates a treeview and populates it with TreeViewItems. The Converter simply takes the name and spits back a StackPanel with 2 different coloured strings. The only way I've found that I can actually use that stackpanel visually is by setting it in the header of a TreeViewItem, this however doesn't work optimally as a TreeViewItem is created programatically already.
The result is that I can't click the label(header) but it looks fancy, however I discovered that there's a big space in front of the label that I can click, which must then be from the generated TreeViewItem. I really need the label to contain a stackpanel of 2 textblocks, is there a solution for this?
<UserControl.Resources>
<XmlDataProvider x:Key="MyXmlProvider" Source="LogansTest.xml" XPath="/Items"/>
<customScripts:NameGeneration x:Key="NameGeneration"/>
<HierarchicalDataTemplate x:Key="NodeTemplate" ItemsSource="{Binding XPath=./*}">
<TreeViewItem x:Name="nodetext"/>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=NodeType}" Value="Element">
<Setter TargetName="nodetext" Property="Header" Value="{Binding Converter={StaticResource NameGeneration}}"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</UserControl.Resources>
EDIT
Following mm8's suggestion I've edited my code, I've uploaded my XAML in its entirety, it is no longer generating the tree, I'm pretty new to XAML so I can't see what I'm doing wrong, heh. Ran a few tests, the converter isn't being called and the treeview is just empty where before it had all the nodes of the XML file
<UserControl x:Class="XmlOutline.OutlineWindowControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vsshell="clr-namespace:Microsoft.VisualStudio.Shell;assembly=Microsoft.VisualStudio.Shell.15.0"
xmlns:customScripts="clr-namespace:XmlOutline.CustomScripts"
Background="{DynamicResource {x:Static vsshell:VsBrushes.WindowKey}}"
Foreground="{DynamicResource {x:Static vsshell:VsBrushes.WindowTextKey}}"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Name="MyToolWindow">
<UserControl.Resources>
<XmlDataProvider x:Key="MyXmlProvider" Source="LogansTest.xml" XPath="/Items"/>
<customScripts:NameGeneration x:Key="NameGeneration"/>
</UserControl.Resources>
<Grid x:Name="TreeGrid" DataContext="MyXmlProvider">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TreeView Name="TreeItems" Visibility="Hidden"
ItemsSource="{Binding Source={StaticResource MyXmlProvider}}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
VirtualizingStackPanel.IsVirtualizing="False"
VirtualizingStackPanel.VirtualizationMode="Standard"
Background="#252525"
SelectedItemChanged="TreeView_OnSelectedItemChanged">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding XPath=./*}"/>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=NodeType}" Value="Element">
<Setter Property="Header" Value="{Binding Converter={StaticResource NameGeneration}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</Grid>
</UserControl>
EDIT This is the code that sets the new datasource whenever a new XML document is opened.
var provider = new XmlDataProvider()
{
Source = new Uri(gotFocus.Document.Path + gotFocus.Document.Name),
XPath = "./*"
};
OutlineWindowInstance.TreeItems.DataContext = provider;
By the way, the entire GIT repo can be found here: https://github.com/LoganLabster/VsXmlOutline
You are not supposed to create another TreeViewItem
container in an HierarchicalDataTemplate
. Try to define an ItemContainerStyle
that sets the Header
property:
<TreeView ItemsSource="{Binding Source={StaticResource MyXmlProvider}}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding XPath=./*}" />
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=NodeType}" Value="Element">
<Setter Property="Header" Value="{Binding Converter={StaticResource NameGeneration}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
Thanks to @mm8 I managed to find the answer, it was really quite simple once I figured it out (which took way too long, doh). Rather than set the StackPanel to the treeviewitem header, I built the StackPanel in XAML and set the values there one at a time, and voila, it worked.
<UserControl x:Class="XmlOutline.OutlineWindowControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vsshell="clr-namespace:Microsoft.VisualStudio.Shell;assembly=Microsoft.VisualStudio.Shell.15.0"
xmlns:customScripts="clr-namespace:XmlOutline.CustomScripts"
Background="{DynamicResource {x:Static vsshell:VsBrushes.WindowKey}}"
Foreground="{DynamicResource {x:Static vsshell:VsBrushes.WindowTextKey}}"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Name="MyToolWindow">
<UserControl.Resources>
<XmlDataProvider x:Key="MyXmlProvider" Source="LogansTest.xml" XPath="/Items"/>
<customScripts:NameGeneration x:Key="NameGeneration"/>
</UserControl.Resources>
<Grid x:Name="TreeGrid" DataContext="MyXmlProvider">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TreeView Name="TreeItems" Visibility="Hidden"
ItemsSource="{Binding}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
VirtualizingStackPanel.IsVirtualizing="False"
VirtualizingStackPanel.VirtualizationMode="Standard"
Background="#252525"
SelectedItemChanged="TreeView_OnSelectedItemChanged"
TreeViewItem.Expanded="TreeViewItem_Expanded"
TreeViewItem.Collapsed="TreeViewItem_Collapsed">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate x:Name="myTest" ItemsSource="{Binding XPath=./*}">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="Title" Foreground="LightSkyBlue" FontSize="14"/>
<TextBlock x:Name="SubTitle" Foreground="YellowGreen" FontSize="13"/>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=NodeType}" Value="Element">
<Setter TargetName="Title" Property="Text" Value="{Binding Path=Name}"/>
<Setter TargetName="SubTitle" Property="Text" Value="{Binding Converter={StaticResource NameGeneration}}" />
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</UserControl>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.