C# 在WPF中,当xml文档在运行时发生更改时,如何刷新xmlDataProvider?

C# 在WPF中,当xml文档在运行时发生更改时,如何刷新xmlDataProvider?,c#,wpf,xml,binding,C#,Wpf,Xml,Binding,我正试图在VisualStudioWPF中创建一个图像查看器/相册创建者。每个相册的图像路径存储在一个xml文档中,我绑定到该文档以在列表框中显示每个相册的图像。 问题是在运行时添加图像或相册并将其写入xml文档时。我似乎无法更新xml文档的绑定,因此它们也会显示新的图像和相册。 在XmlDataProvider上调用Refresh(),不会改变任何内容。 我不想重做XmlDataProvider的绑定,只想让它再次从同一个源读取 XAML: } 非常感谢您的帮助 在这种情况下,我认为正确的方法

我正试图在VisualStudioWPF中创建一个图像查看器/相册创建者。每个相册的图像路径存储在一个xml文档中,我绑定到该文档以在列表框中显示每个相册的图像。 问题是在运行时添加图像或相册并将其写入xml文档时。我似乎无法更新xml文档的绑定,因此它们也会显示新的图像和相册。 在XmlDataProvider上调用
Refresh()
,不会改变任何内容。 我不想重做XmlDataProvider的绑定,只想让它再次从同一个源读取

XAML:

}


非常感谢您的帮助

在这种情况下,我认为正确的方法是使用
ObservableCollection
,并将其绑定到
列表视图的
项资源
属性。因此,只需使用对象,而不必使用XML文件

编辑:

整个概念是使用
Refresh()
。下一个示例是works。检查文档保存后是否进行了
Refresh()
调用

<ListView x:Name="uiList" ItemsSource="{Binding}">
    <ListView.DataContext>
        <XmlDataProvider x:Name="DataSource" Source="c:\XMLFile.xml" XPath="/root/item"  />
    </ListView.DataContext>
    <ListView.ItemTemplate>
        <DataTemplate>
            <Border Width="40" Height="40" Background="Gray">
                <Label Content="{Binding Attributes[0]}" />
            </Border>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

可能的问题和解决方案#1 您是否也在Application.Resources块中声明了此XmlDataProvider资源

如果这样做,XAML UI列表框元素“thumbnailList”将引用XmlDataProvider的网格面板实例。我猜,因为我看不到Window-CS文件构造函数中的代码,所以在处理XmlDataProvider时,您引用了XmlDataProvider的应用程序级实例,如中所示

XmlDataProvider XmlDataProvider=Application.Current.FindResource(“图像”)作为XmlDataProvider

XmlDocument xDoc=xmlDataProvider.Document

如果是这种情况,请从网格元素中删除XmlDataProvider资源。现在,当您的代码隐藏更新XML文件时,UI将自动更新


可能的问题和解决方案#2 我从addImage()方法中看到,您引用了一个名为“xDoc”的实例变量

另一种可能性是,您正在窗口构造函数中创建一个新的XmlDocument,而不是引用XAML创建的XmlDocument对象。如果是,则获取当前XmlDocument的实例,而不是创建新实例。确保声明资源 并从网格元素中删除资源声明

XmlDataProvider XmlDataProvider=Application.Current.FindResource(“图像”)作为XmlDataProvider

或者引用网格元素上的资源(您需要向网格中添加一个名称),并且不在Application.Resources块中声明该资源

XmlDataProvider XmlDataProvider=grid.FindResource(“图像”)作为XmlDataProvider

XmlDocument xDoc=xmlDataProvider.Document

现在,当您的代码隐藏更新XML文件时,UI将自动更新


结论 如果在代码中声明这两个类实例变量

XmlDataProvider XmlDataProvider

XmlDataProvider gridXmlDataProvider

并在窗口构造函数中包含此代码

xmlDataProvider=Application.Current.FindResource(“图像”)作为xmlDataProvider

gridXmlDataProvider=grid.FindResource(“图像”)作为XmlDataProvider

在添加节点并保存XML文档更改后,在addImage事件处理程序中停止。假设您最初从xmlDataProvider加载了oDoc,如上所示。在调试模式下运行并打开一个监视窗口,检查xmlDataProvider和gridXmlDataProvider的内容。在每个属性上打开Document属性,并比较InnerXml属性的内容。在xmlDataProvider(应用程序级的资源)上,您可以找到 将反映对XML文件的最新节点更改。gridXmlDataProvider(XAMLUI元素的资源)上的情况并非如此。InnerXml属性未显示任何更改。没有更改,不需要更新UI

仅供参考,我遇到了问题#1-Application.Resources块和Window.Resources块中声明的XmlDataProvider资源相同。我从后一个声明开始,在通过Application.Current.FindResource(“name”)引用XmlDataProvider实例后,遇到了一个异常错误,将声明复制并粘贴到Application.Resources块中,将资源声明保留在Window.Resources块中,从而产生了两个引用问题。XAML UI使用窗口数据上下文,而我的代码隐藏使用应用程序数据上下文更新XML文件!每当我从XML文件中添加或删除节点时,UI(列表框)都不会得到更新

顺便说一句,XmlDataProvider已经实现了自己的通知机制,不需要使用ObservableCollection。oProv.Refresh()不会导致绑定UI的刷新,因为它可能指向XmlDataProvider的不同实例(网格元素的),就该实例而言,没有发生任何更改

这个答案对你来说可能太晚了,但我刚刚发现了这个东西,我想我可以分享它。

在xml中

取自

我在下面用过

        XmlDataProvider xdp = this.Resources["userDataXmlDataProvider1"]  as XmlDataProvider;
        xdp.Source = new Uri(MyPath + @"\Projects.xml");

        FileSystemWatcher watcher = new FileSystemWatcher();
        //set the path of the XML file appropriately as per your requirements
        watcher.Path = MyPath;

        //name of the file i am watching
        watcher.Filter = "Projects.xml";

        //watch for file changed events so that we can refresh the data provider
        watcher.Changed += new FileSystemEventHandler(file_Changed);

        //finally, don't forget to enable watching, else the events won't fire           
        watcher.EnableRaisingEvents = true;

在我的用户控制下

    <UserControl.Resources>
    <XmlDataProvider x:Key="userDataXmlDataProvider1" XPath="Projects/Project" IsAsynchronous="True" />
    <CollectionViewSource x:Key="userDataCollectionViewSource1" Source="{StaticResource userDataXmlDataProvider1}"/>
    </UserControl.Resources>

    <Grid DataContext="{StaticResource userDataXmlDataProvider1}">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="3*"/>
    </Grid.RowDefinitions>
    <ListBox x:Name="listBox1" Grid.Row="1"
             ItemsSource="{Binding}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal" Margin="8,0,8,0">
                    <Label Content="{Binding XPath=ProjectName}" Width="100" Margin="5" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

</Grid>


您使用的是哪个.Net版本?如果是3.5版或更高版本,则更倾向于使用XDocument,a请使用XML:):我对XML文件没有问题,它已正确更新。只是xml的新内容没有显示在UI列表框中,我找不到如何更新或刷新以使其显示出来。下次我启动应用程序时,它就在那里了。
public MainWindow()
{
    InitializeComponent();
    uiList.SelectionChanged += new SelectionChangedEventHandler(uiList_SelectionChanged);
}

void uiList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    string sFile = @"c:\XMLFile.xml";
    XDocument oDoc = XDocument.Load(sFile);
    oDoc.Root.Add(
        new XElement("item", new XAttribute("name", "test3"))
    );
    oDoc.Save(sFile);

    XmlDataProvider oProv = uiList.DataContext as XmlDataProvider;
    oProv.Refresh();
}
    <XmlDataProvider Source="XMLFile1.xml" XPath="Data"  DataChanged="XmlDataProvider_DataChanged"></XmlDataProvider>
</Window.DataContext>
  private void XmlDataProvider_DataChanged(object sender, EventArgs e)
        {
            Dispatcher.BeginInvoke((Action)(() =>
            {
                XmlDataProvider oProv = this.DataContext as XmlDataProvider;
                oProv.Refresh();
            }));
        }
        XmlDataProvider xdp = this.Resources["userDataXmlDataProvider1"]  as XmlDataProvider;
        xdp.Source = new Uri(MyPath + @"\Projects.xml");

        FileSystemWatcher watcher = new FileSystemWatcher();
        //set the path of the XML file appropriately as per your requirements
        watcher.Path = MyPath;

        //name of the file i am watching
        watcher.Filter = "Projects.xml";

        //watch for file changed events so that we can refresh the data provider
        watcher.Changed += new FileSystemEventHandler(file_Changed);

        //finally, don't forget to enable watching, else the events won't fire           
        watcher.EnableRaisingEvents = true;
    void file_Changed(object sender, FileSystemEventArgs e)
    {
        XmlDataProvider xdp = this.Resources["userDataXmlDataProvider1"] as XmlDataProvider;
        xdp.Refresh();

    }
    <UserControl.Resources>
    <XmlDataProvider x:Key="userDataXmlDataProvider1" XPath="Projects/Project" IsAsynchronous="True" />
    <CollectionViewSource x:Key="userDataCollectionViewSource1" Source="{StaticResource userDataXmlDataProvider1}"/>
    </UserControl.Resources>

    <Grid DataContext="{StaticResource userDataXmlDataProvider1}">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="3*"/>
    </Grid.RowDefinitions>
    <ListBox x:Name="listBox1" Grid.Row="1"
             ItemsSource="{Binding}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal" Margin="8,0,8,0">
                    <Label Content="{Binding XPath=ProjectName}" Width="100" Margin="5" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

</Grid>