У меня есть приложение WPF, которое связывает DataGrid с документом XML с помощью XmlDataProvider. Все работает отлично, за исключением того, что я пытаюсь «сохранить» / записать в файл XML по событию NodeChanged вместо кнопки или другого механизма, запускаемого пользователем. К сожалению, обработчик 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 XPath=@Value, 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 XML.xml, поместить его в bin / Debug проекта и добавить в проект как «существующий элемент».
UPDATE
Спасибо, Роберт, за указание на проблему!
Вот еще более интересная ситуация. Если вы просто добавите обработчик события LayoutUpdated в MainWindow в мой пример кода, как показано ниже, вы получите очень странное поведение в том, что событие 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!!
}
}
}