Question may need to be edited since I don't think I necessarily know the best way to do this.
Current config of my WPF usercontrol. I have a XmlDataProvider that contains some static XML Elements that I use to populate a TreeView control. I currently use a HierarchicalDataTemplate to bind to a TreeViewItem
<HierarchicalDataTemplate x:Key="SiteTemplate" ItemsSource="{Binding XPath=pci}">
<TextBlock Text="{Binding XPath=@Name}"/>
</HierarchicalDataTemplate>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True"/>
</Style>
TreeView control
<TreeView ItemsSource="{Binding Source={StaticResource SharePointSites}}"
ItemTemplate="{StaticResource SiteTemplate}"
I would like to replace the current static resource with data that is loaded from a xml file at runtime. Additionally I want the user to be able to modify the nodes of the treeview at runtime and have those values written back to the same xml file. I have been reading up about using the MVVM pattern and creating an IObservable class. Can someone point me in the right direction?
Edit: Perhaps I've asked this question in a sub-optimal way. Can anyone recommend improvements or make edits to improve the quality of the question in anyway?
I have no access to my Visual Studio environment so the code below will be full of compilation errors... So please treate this as a pseudo code...
Assuming your Xml structure is something like this....
<MyItem Name="Root">
<MyItem Name="ABC"/>
<MyItem Name="PQR">
<MyItem Name="IJK"/>
</MyItem>
<MyItem Name="XYZ"/>
</MyItem>
Bind your ItemsSource thru a converter , say MyXmlToObjectDataSourceConverter.
<TreeView ItemsSource="{Binding Source={StaticResource SharePointSites},
Converter={StaticResource MyXmlToObjectDataSourceConverter}}" ... />
In MyXmlToObjectDataSourceConverter.Convert() method return this...
public object Convert(...)
{
return new ObservableCollection<XmlNodeWrapper>(
((XmlDataProvider)value).Document.SelectNodes("MyItem").Select(
d => new XmlNodeWrapper(d)).ToList())
}
XmlNodeWrapper class will maintain the 'node' internally so that when updates take place thru property Setters, you can update the node based attribute back... like this...
public class XmlNodeWrapper : INotifyPropertyChanged
{
private XmlNode node;
private ObservableCollection<XmlNodeWrapper> children;
public XmlNodeWrapper(XmlNode node)
{
this.node = node;
}
public ObservaleCollection<XmlNodeWrapper> Children
{
get
{
if (children == null)
{
this.children
= new ObservableCollection<XmlNodeWrapper>(
this.node.ChildNodes.Select(
d => new XmlNodeWrapper(d)).ToList());
}
return children;
}
}
public string Name
{
get
{
return node.Attributes["Name"];
}
set
{
node.Attributes["Name"] = value;
this.PropertyChanged["Name"];
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void PropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
Then replace all XPath attributes in your XAML with standard Path.
<HierarchicalDataTemplate x:Key="SiteTemplate"
ItemsSource="{Binding Path=Children}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With