1
votes

I have a WPF DataGrid which is bound to some nodes in my XML file.

<Settings xmlns="">
  <Profiles xmlns="" ActiveProfile="1">
    <Profile Id="0" Desc="- none -" Port="0" Baud="0" DataBits="0" Parity="0" StopBits="0" CharDelay="0" ReadTimeout="0" ProcInterval="0" SetInterval="0" DecInterval="0" ChartInterval="0" SaveInterval="0">
      <PIDs>
        <PID Address="1" SetPoint="one" ProcVal="one" />
        <PID Address="2" SetPoint="two" ProcVal="two" />
        <PID Address="3" SetPoint="three" ProcVal="three" />
      </PIDs>
    </Profile>
    <Profile Id="1" Desc="Test Profile 1" Port="1" Baud="19200" DataBits="7" Parity="0" StopBits="3" CharDelay="1" ReadTimeout="100" ProcInterval="100" SetInterval="0" DecInterval="0" ChartInterval="0" SaveInterval="0">
      <PIDs>
        <PID Address="4" SetPoint="four" ProcVal="four" />
        <PID Address="5" SetPoint="five" ProcVal="five" />
        <PID Address="6" SetPoint="six" ProcVal="six" />
      </PIDs>
    </Profile>

Here is some pertinent XAML:

<XmlDataProvider x:Name="MySettings" x:Key="MySettings" Source="Settings.xml" XPath="Settings" IsAsynchronous="False" IsInitialLoadEnabled="True"/>
<XmlDataProvider x:Name="PIDData" x:Key="PIDData" Source ="Settings.xml" XPath="Settings/Profiles"/>

<ComboBox Name="cboProfile" Width="150" Padding="10,3,4,3" ItemsSource="{Binding Source={StaticResource MySettings}, XPath=Profiles/Profile}"
          SelectedValuePath="@Id" DisplayMemberPath="@Desc"
          SelectedValue="{Binding Mode=TwoWay, Source={StaticResource MySettings}, XPath=Profiles/@ActiveProfile}"/>

<DataGrid Name="dgPIDData" AutoGenerateColumns="False" Height="201" HorizontalAlignment="Left" Margin="233,137,0,0" VerticalAlignment="Top" Width="444"
          DataContext="{Binding Source={StaticResource PIDData}}" ItemsSource="{Binding XPath=Profile[@Id\=../@ActiveProfile]/PIDs/PID}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Address" Binding="{Binding XPath=@Address}"/>
        <DataGridTextColumn Header="Set Point" Binding="{Binding XPath=@SetPoint}"/>
        <DataGridTextColumn Header="Proc Val" Binding="{Binding XPath=@ProcVal}"/>
    </DataGrid.Columns>
</DataGrid>

Here is some code-behind:

Private settingsDoc As XmlDocument
Private dp As XmlDataProvider

Private Sub MainWindow_Initialized(sender As Object, e As System.EventArgs) Handles Me.Initialized

    dp = Me.TryFindResource("MySettings")
    If dp IsNot Nothing Then
        settingsDoc = dp.Document
        settingsText = settingsDoc.OuterXml
    End If

End Sub

Private Sub cboProfile_SelectionChanged(sender As Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles cboProfile.SelectionChanged

    If Me.dgPIDData IsNot Nothing Then
        If dp IsNot Nothing Then
            Stop
        End If
    End If

End Sub

When I run the application, it properly shows items 4, 5 and 6 in the DataGrid. This is because the ItemsSource XPath reads the "ActiveProfile" value from the Profiles node, and uses that to select the proper Profile node. Even in design mode, the DataGrid shows these values.

At run-time, I change the ComboBox from the second item (index 1) to the first item (index 0). The code stops in the SelectionChanged event, so I can poll the "ActiveProfile" value, which changes from "1" to "0" properly, since the ComboBox's binding mode is TwoWay. Unfortunately, the DataGrid does not re-display with items 1, 2 and 3 like it should.

My MainWindow_Closing event has code to save the XML file if it has changed. If I do this, then the next time the application runs, the DataGrid values start at 1, 2 and 3. So the binding is working, and selecting the proper list of items from the XML file, but the DataGrid is just not updating until the next time it loads.

I thought that XmlDataProvider would automatically notify the DataGrid to refresh. I tried doing a DataGrid.Items.Refresh() in the SelectedIndexChanged event, but no luck.

Does anybody have any idea why my DataGrid won't refresh from the XML? Thanks...

1

1 Answers

0
votes

Figured this out myself. I don't know why, but putting this code:

Private Sub settingsDoc_NodeChanged(sender As Object, e As System.Xml.XmlNodeChangedEventArgs) Handles settingsDoc.NodeChanged

    Dim dp As XmlDataProvider = DirectCast(Me.TryFindResource("PIDData"), XmlDataProvider)
    If dp IsNot Nothing Then
        dp.Document = settingsDoc
    End If

End Sub

seems to solve the issue. It shouldn't be required, as both settingsDoc AND XmlDataProvider.Document both reflect the proper value prior to this code being executed. for some reason, the above code forces the DataGrid to refresh.