2009-10-20 74 views
1

到目前爲止,我發現的所有關於數據綁定到XML的東西總是隻能綁定到固定的XML結構。會很好,如果任何人都可以指出我的方向,我迄今爲止所嘗試的所有東西都顯得很尷尬。如何添加新的XmlNode?

這是我想怎樣做:

綁定一個複選框的選中狀態到XML中的一個節點。 因此,檢查該特定節點是否存在於XML中,如果不存在,則不選中。

對於單向結合這不難(結合到與該返回「值!= NULL」一個轉換器的節點)

現在我也想看到這個特定節點添加到/從底層除去XmlDocument的。

有沒有簡單的方法來做到這一點?

我到目前爲止的嘗試是做綁定單向並添加一個CheckedChanged事件處理程序來處理添加/刪除部分。這個代碼很糟糕,它不會更新綁定到這個XmlDataProvider。

作爲一般和簡化問題:什麼是將新的XmlNodes添加到WPF中綁定的Xml結構的好方法?

感謝您的幫助

回答

1

如果有人有興趣,這是我想出了:

的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> 

行爲:

[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; } 
} 

現在這整個事情看起來並不好看完全可以完成工作。 不過這到是揭示一些奇怪的行爲:

  1. 的結合,似乎每一個(我爲什麼要再次每次也就那麼多了)

  2. XmlDataProvider的刷新方法是點擊事件被觸發時被取消設置在Clickhandler執行之前調用一次,就像Refresh第一次執行時一樣,它將原始XmlDocument拉回到XmlDataProvider並關閉當前的XmlDocument。

非常尷尬......如果任何人都可以清理任何東西,非常感謝。

0

據我所知,XmlDataProvider沒有提供的功能來處理節點結構,只有操作值。因此,如果您想操縱節點,您需要編寫代碼,以便通過the XmlDataProvider's Document property提供的XmlDocument實例進行操作。