If anyone is interested, this is what i came up with:
The XAML:
<Window.Resources>
<local:NodeAvailableConverter x:Key="MyConverter"/>
<XmlDataProvider x:Key="xmlsource">
<x:XData>
<main xmlns="">
<sub/>
</main>
</x:XData>
</XmlDataProvider>
</Window.Resources>
<DockPanel DataContext="{Binding Source={StaticResource xmlsource}}">
<CheckBox Content="CheckBox1" DockPanel.Dock="Top">
<i:Interaction.Behaviors>
<local:MyBehavior SourceProv="{StaticResource xmlsource}" XPath="main">
<local:Node Name="sub">
<local:Attribute Name="yeah" Value="added1"/>
</local:Node>
</local:MyBehavior>
</i:Interaction.Behaviors>
</CheckBox>
<CheckBox Content="CheckBox2" DockPanel.Dock="Top">
<i:Interaction.Behaviors>
<local:MyBehavior SourceProv="{StaticResource xmlsource}" XPath="main">
<local:Node Name="sub">
<local:Attribute Name="yeah" Value="added2"/>
</local:Node>
</local:MyBehavior>
</i:Interaction.Behaviors>
</CheckBox>
<Label Content="{Binding OuterXml}" />
</DockPanel>
The Behavior:
[ContentProperty("CustomNode")]
public class MyBehavior : Behavior<CheckBox>
{
protected override void OnAttached()
{
base.OnAttached();
binding = new Binding();
binding.XPath = XPath + "/" + CustomNode.Name;
binding.Mode = BindingMode.OneWay;
binding.Converter = NodeAvailableConverter.Instance;
AssociatedObject.SetBinding(CheckBox.IsCheckedProperty, binding);
AssociatedObject.Click += new RoutedEventHandler(AssociatedObject_Click);
SourceProv.Refresh();
}
void AssociatedObject_Click(object sender, RoutedEventArgs e)
{
var parent = SourceProv.Document.SelectSingleNode(XPath);
if(AssociatedObject.IsChecked==true)
{
var newelement = SourceProv.Document.CreateElement(CustomNode.Name);
foreach (var at in CustomNode.Attributes)
newelement.SetAttribute(at.Name, at.Value);
parent.AppendChild(newelement);
}
else if (AssociatedObject.IsChecked == false)
parent.RemoveChild(parent.SelectSingleNode(CustomNode.Name));
SourceProv.Refresh();
AssociatedObject.SetBinding(CheckBox.IsCheckedProperty, binding);
}
public XmlDataProvider SourceProv { get; set; }
public Node CustomNode { get; set; }
public String XPath { get; set; }
private Binding binding { get; set; }
}
public class NodeAvailableConverter : IValueConverter
{
private static NodeAvailableConverter _instance;
public static NodeAvailableConverter Instance
{
get
{
if (_instance == null)
_instance = new NodeAvailableConverter();
return _instance;
}
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value != null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ContentProperty("Attributes")]
public class Node
{
public string Name { get; set; }
private List<Attribute> _attributes;
public List<Attribute> Attributes { get
{
if (_attributes == null)
_attributes = new List<Attribute>();
return _attributes;
} }
}
public class Attribute
{
public string Name { get; set; }
public string Value { get; set; }
}
Now this whole thing doesn't look nice at all, but gets the job done.
It does reveal some strange behaviors though:
The Binding seems to be unset every time the Click event gets triggered (thats why i set it every time again)
XmlDataProvider's Refresh method has to be called once before the clickhandler executes, as when Refresh gets executed the first time, it seems like pulling the original XmlDocument back to the XmlDataProvider and dismisses the current XmlDocument.
very awkward... if anyone can clear anything up, it's much appreciated.