I have created treeview with dynamically filled from xml file hierarchy and I have issue. In treeview nested hierarchy was recursive duplicate and get result like this :
XAML-markup of treeview:
<TreeView x:Name="leftNestingTreeView" ItemsSource="{Binding Fragments, UpdateSourceTrigger=PropertyChanged}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ChildFragments}" DataType="{x:Type a:FragmentModel}">
<TextBlock Text = "{Binding fragmentId}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Code of source:
Fragments = NestingTree.Values.ToList();
OnPropertyChanged(nameof(Fragments));
XML file:
<NestingTree>
<fragment id="root_fragment" name=" n1">
<parent id="" name="" />
<childs count="1">
<child id="f1" name="frag1" />
</childs>
</fragment>
<fragment id="f1" name="frag1">
<parent id="root_fragment" name="n1" />
<childs count="1">
<child id="f2" name="frag2" />
</childs>
</fragment>
<fragment id="f2" name="frag2">
<parent id="f1" name="frag1" />
<childs count="0" />
</fragment>
</NestingTree>
UPDATE
NestingTree is Dictionary<string,FragmentModel>, where keys is ids and values is fragments.
Code of FragmentModel:
public class FragmentModel : INotifyPropertyChanged
{
public string fragmentId { get; set; }
private string fragmentName { get; set; }
public string FragmentName
{
get { return fragmentName; }
set
{
fragmentName = value;
OnPropertyChanged(nameof(FragmentName));
}
}
public FragmentModel ParentFragment { get; set; }
public List<FragmentModel> ChildFragments { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs(propertyName));
}
}
}
Filling of NestingTree data from XML file:
XDocument xmlNestingTree = XDocument.Load("nesting_tree.xml");
if (xmlNestingTree.Element("NestingTree") is not null)
{
int count = 0;
foreach (XElement fragment in
xmlNestingTree.Element("NestingTree").Elements("fragment"))
{
string id = fragment.Attribute("id").Value;
FragmentModel f = new FragmentModel
{
fragmentId = id,
FragmentName = fragment.Attribute("name").Value,
};
nestingTree.Add(id, f);
}
foreach (XElement fragment in
xmlNestingTree.Element("NestingTree").Elements("fragment"))
{
FragmentModel currentFragment = nestingTree.Values.Where(f => f.fragmentId == fragment.Attribute("id").Value).FirstOrDefault();
FragmentModel parentFragment = nestingTree.Values.Where(f => f.ChildFragments.Contains(currentFragment)).FirstOrDefault();
currentFragment.ParentFragment = parentFragment;
if (Int32.TryParse(fragment.Element("childs").Attribute("count").Value, out count) && count > 0)
{
foreach (XElement child in fragment.Element("childs").Elements("child"))
{
FragmentModel currentChildFragment = nestingTree.Values.Where(f => f.fragmentId == child.Attribute("id").Value).FirstOrDefault();
currentFragment
.ChildFragments
.Add(currentChildFragment);
}
}
}
NestingTree = nestingTree;
}
Possible approaches of saving tree data are:
Your xml uses both approaches in the same time. I'd suggest to remove 'parent_id' (code will recursively read each xml element and build tree) or remove 'children' (in this case code will read all elements to list and build tree by levels, first search root fragment(s) with no parent, then loop by fond list and search fragments whose parent is current item, etc).
Here is example of second approach: Read a XML tree structure recursively in a List<T> with children lists<T>