I have an ObservableCollection that I populate during runtime which is bound to the TreeView. When the collection is updated, the root object of the collection appears in the TreeView without any way to expand it (see the first image).
I assumed this meant there was an issue with the binding, however, removing TreeView.ItemCotainerStyle tag makes the arrow appear and everything works as intended (see the second image). This behaviour works in reverse too, if the style tag isn't in the view and I add it after the collection is updated then the arrows will appear.
The style tags aren't necessary for any function in my project to work, they're just leftover from an example I was working from.
<TreeView ItemsSource="{Binding CompileMessages}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded"
Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected"
Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="FontWeight"
Value="Normal" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type models:CompileMessagesDto}"
ItemsSource="{Binding Path=Children}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="{Binding Path=State}"
Margin="3"
Foreground="White" />
<TextBlock Text="{Binding Path=Path}"
FontWeight="Normal"
Foreground="White"
FontSize="12"
Margin="3" />
<TextBlock Text="{Binding Path=Description}"
FontWeight="Normal"
FontSize="12"
Foreground="#ff8000"
Margin="3" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
public class CompileMessagesDto
{
public string State { get; set; } = "";
public string Path { get; set; } = "";
public string Description { get; set; } = "";
public string Parent { get; set; }
public ObservableCollection<CompileMessagesDto> Children { get; set; } = new ObservableCollection<CompileMessagesDto>();
}
TreeView after removing the style tag
Initialising the collection with test values displays the arrows, it's only after the collection is modified during runtime that the TreeView behaves like this. I use MaterialDesignInXaml if that helps at all.
Edit (how the collection is updated)
It's definitely not the best way to do it but I loop through a collection of compiler messages and add them to the collection. I'm left with every object and a reference to their parent.
foreach (CompilerResultMessage message in messages)
{
CompileMessagesDto compileMessage = new CompileMessagesDto { State = message.State.ToString(), Path = message.Path, Description = message.Description, Parent = parent };
MessageCrawl(message.Messages, message.Path);
CompileMessages.Add(compileMessage);
}
Then I set each object's children, and remove every object from the collection that isn't the root object. Leaving the root with the tree of children in it.
List<CompileMessagesDto> removeItems = new List<CompileMessagesDto>();
foreach (CompileMessagesDto message in CompileMessages)
{
message.Children = new ObservableCollection<CompileMessagesDto>(CompileMessages.Where(c => c.Parent == message.Path));
if (message.Parent != "Root") { removeItems.Add(message); }
}
foreach (CompileMessagesDto message in removeItems)
{
CompileMessages.Remove(message);
}
Style
throw errors. Your data models neither have aIsExpanded
nor aIsSelected
property. – BionicCode