2010-11-02 121 views
0

我有一個WPF應用程序,該應用程序使用XmlDataProvider將DataGrid綁定到XML文檔。除了我試圖在NodeChanged事件上「保存」/寫入XML文件,而不是使用按鈕或其他用戶觸發的機制之外,一切正常。不幸的是,我創建的NodeChanged處理程序沒有被拾取。希望得到任何幫助,找出爲什麼它不被解僱。WPF:NodeChanged事件沒有觸發

XAML:

<Grid Name="Grid" Loaded="Grid_Loaded"> 
    <Grid.DataContext> 
     <XmlDataProvider x:Name="MyData" Source="Data.xml" XPath="Nodes/Node" /> 
    </Grid.DataContext> 
    <DataGrid AutoGenerateColumns="False" Name="dataGrid1" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" SelectionUnit="FullRow" SelectionMode="Single" Margin="0,0,0,50"> 
     <DataGrid.Columns> 
     <DataGridTextColumn Header="Header" Binding="{Binding [email protected], Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/> 
     </DataGrid.Columns> 
    </DataGrid> 
    <Button Content="Save" Height="23" HorizontalAlignment="Left" Margin="416,276,0,0" Name="SaveButton" VerticalAlignment="Top" Width="75" Click="SaveButton_Click" /> 
    </Grid> 

代碼隱藏:


namespace WpfApplication1 
{ 
    public partial class MainWindow : Window 
    { 
    public MainWindow() 
    { 
     InitializeComponent(); 

     string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); 
     MyData.Source = new Uri(appPath + "/Data.xml"); 
    } 

    private void SaveButton_Click(object sender, RoutedEventArgs e) 
    { 
     string source = MyData.Source.LocalPath; 
     MyData.Document.Save(source); 
    } 

    private void Grid_Loaded(object sender, RoutedEventArgs e) 
    { 
     MyData.Document.NodeChanged += new XmlNodeChangedEventHandler(Document_NodeChanged); 
    } 

    void Document_NodeChanged(object sender, XmlNodeChangedEventArgs e) 
    { 
     MessageBox.Show("Node changed"); 
    } 
    } 
} 

XML數據文件:

<Nodes> 
    <Node Value="test1" /> 
    <Node Value="test3" /> 
    <Node Value="ttt" /> 
</Nodes> 

複製,你可以粘貼入一個新的WPF應用程序,命名XML數據文件Data.xml,將其放入項目的bin/Debug中,並將其作爲「現有項目」添加到項目中。

UPDATE

感謝羅伯特指出的問題!

這是一個更有趣的情況。如果你只需要添加一個LayoutUpdated事件處理程序的主窗口,以我的示例代碼如下,你將在NodeChanged事件變得非常怪異的行爲實際上將被解僱如果顯示一個完全無關的MessageBox:

public partial class MainWindow : Window 
{ 
    private bool event_activated = false; 

    public MainWindow() 
    { 
     InitializeComponent(); 
     string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); 
     MyData.Source = new Uri(appPath + "/Data.xml"); 
    } 

    private void SaveButton_Click(object sender, RoutedEventArgs e) 
    { 
     string source = MyData.Source.LocalPath; 
     MyData.Document.Save(source); 
    } 

    private void Grid_Loaded(object sender, RoutedEventArgs e) 
    { 
     MyData.Document.NodeChanged += new XmlNodeChangedEventHandler(Document_NodeChanged); 
    } 

    private void Document_NodeChanged(object sender, XmlNodeChangedEventArgs e) 
    { 
     MessageBox.Show("Node changed"); 
    } 

    private void Window_LayoutUpdated(object sender, EventArgs e) 
    {  
     if (!event_activated) 
     { 
      event_activated = true; 
      MessageBox.Show("LayoutUpdated"); // <-- NodeChanged is fired with this one line of code, and not fired if you comment this line out!! 
     } 
    } 
} 

回答

0

一點也沒有」因爲節點的值不會改變,所以只會發生名爲Value的屬性。它在documentation中說明:

當屬於此文檔的節點的值已被更改時發生。 ... 此事件僅適用於具有值的節點。

如何使用DataGrid.CellEditEnding或DataGrid.RowEditEnding代替?

更新:

你是正確的,NodeChanged將火屬性爲好。儘管如此,我確實在你的漂亮的repro應用程序中發現了問題如果我註釋掉你的構造函數代碼,它一切正常。您已經在Xaml中設置了源代碼。看起來,這段代碼觸發了一個內部處理的異常,它使XmlDataProvider處於損壞狀態。

public MainWindow() 
    { 
    InitializeComponent(); 
    //string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); 
    //MyData.Source = new Uri(appPath + "/Data.xml"); 
    } 

您可以在調試輸出中看到異常。 WPF似乎喜歡默默地失敗,並讓你想知道。

+0

感謝羅伯特,但不是根據XmlNode.Value和XmlNodeType枚舉的文檔屬性的節點類型?

在任何情況下,我改變了我的XML數據文件佈局:

  Test 1  


而改變XAML相應。該應用程序仍然不會觸發NodeChanged事件,但寫入XML文件就好了。

關於基於DataGrid的事件,我計劃將多個組件都綁定到同一個XmlDataProvider源,因此爲所有這些事件連接事件會很痛苦。 – Turar 2010-11-02 23:04:42

+0

對不起,我正在努力格式化。以下是新的XML結構。 – Turar 2010-11-02 23:12:26

+0

測試1個 測試2 Turar 2010-11-02 23:12:42