WPF DataGrid mit XML Daten füllen



  • Hallo zusammen,

    Ich versuche nun schon seit Stunden ein DataGrid mit einem XML Dokument zu füllen, und scheitere schon an der Grundlagen. Habe etliche Beispiele gefunden, verstehe das System dahinter aber einfach nicht, da mir die Beispiele einfach zu komplex sind.

    Es gibt eine Combobox welche Pfadangaben zu XML Dateien enthält. Bei Auswahl soll das Dokument im DataGrid eingelesen werden, Spalten und Zeilen automatisch füllen (XML Tags sind nicht variabel).

    Wie gehe ich hier Schritt für Schritt am besten vor ?
    Wer erhält eine Bindung mit wem, und welche Art von Bindung ?
    DataContext, XMLDataProvider, ItemSource - wo liegt der Unterschied ?



  • Lesestoff: Exemplarische Vorgehensweise: Einlesen von XML-Daten in ein Dataset

    Sollte eigentlich alle Unklarheiten beseitigen ... 🤡



  • Hallo shaun1981,

    und hier wie man direkt ein WPF DataGrid mit XML-Daten befüllt (per XElement): http://blogs.msdn.com/b/wpfsdk/archive/2008/11/25/a-datagrid-sample-using-xml-data.aspx



  • Erstmal danke für die Links. Habe aber weiterhin Schwierigkeiten ...

    Damit ihr nicht denkt das ich tatenlos auf Antworten warte, hier der Code:

    Diese XML Datei liegt im Benutzerverzeichniss:

    <?xml version="1.0"?>
    <!--Versionsangabe: V1.0-->
    <Fragen>
      <F0>
        <Fachbereich>Backwaren</Fachbereich>
        <Schwierigkeit>leicht</Schwierigkeit>
        <Typ>2</Typ>
        <Feedback>kein Feedback</Feedback>
        <ID>7b29bc76-b541-43b2-9b4f-2dfa57af66dd</ID>
        <Frage>Wie werden Backtriebmittel unterteilt ?</Frage>
        <Antworten>
          <A1>biologische Triebmittel</A1>
          <A2>chemische Triebmittel</A2>
          <A3>physikalische Triebmittel</A3>
          <A4>organische Triebmittel</A4>
          <A5>anorganische Triebmittel</A5>
        </Antworten>
        <richtigeAntworten>
          <A1>biologische Triebmittel</A1>
          <A2>chemische Triebmittel</A2>
          <A3>physikalische Triebmittel</A3>
        </richtigeAntworten>
        <FrageBild />
        <FeedBackBild />
      </F0>
      <F1>
        <Fachbereich>Backwaren</Fachbereich>
        <Schwierigkeit>leicht</Schwierigkeit>
    

    XAML:

    <Border x:Name="DataGridBorder" Margin="0" Grid.Row="1" >
                    <DataGrid BorderBrush="Black" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" SelectionMode="Single" 
                              ColumnWidth="Auto" GridLinesVisibility="Horizontal" Margin="4" BorderThickness="0" Name="dataGridView1" CanUserAddRows="True" 
                              CanUserDeleteRows="True" AutoGenerateColumns="True" FontSize="9.333" OverridesDefaultStyle="False" 
                              ItemsSource="{ Binding }">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="Typ" Binding="{Binding Path=Attribute[Typ].Value}"  />
                            <DataGridTextColumn Header="Fachbereich" Binding="{Binding Path=Attribute[Fachbereich].Value}"  />
                            <DataGridTextColumn Header="Schwierigkeit" Binding="{Binding Path=Attribute[Schwierigkeit].Value}"  />
                            <DataGridTextColumn Header="Frage" Binding="{Binding Path=Attribute[Frage].Value}"  />
                            <DataGridTextColumn Header="Antworten" Binding="{Binding Path=Attribute[Antworten].Value}"  />
                            <DataGridTextColumn Header="richtigeAntworten" Binding="{Binding Path=Attribute[richtigeAntworten].Value}"  />
                            <DataGridTextColumn Header="Feedback" Binding="{Binding Path=Attribute[Feedback].Value}"  />
                            <DataGridTextColumn Header="ID" Binding="{Binding Path=Attribute[ID].Value}"  />
    
                        </DataGrid.Columns>
                        <DataGrid.Background>
    						<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    							<GradientStop Color="Black" Offset="0"/>
    							<GradientStop Color="{DynamicResource myGreenBrush}" Offset="1"/>
    						</LinearGradientBrush>
    					</DataGrid.Background>
                    </DataGrid>
    
    <ComboBox x:Name="KatalogComboBox"[b]DropDownOpened="KatalogComboBox_DropDownOpened"[/b] FontSize="10" [b]SelectionChanged="KatalogComboBox_SelectionChanged"[/b] SelectedIndex="0" IsSynchronizedWithCurrentItem="True"></ComboBox>
    

    Das Event dazu:

    private void KatalogComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                //dataGridView1.DataContext = IInstanzPool.valueDiskIO.loadXMLDocument(IInstanzPool, KatalogComboBox.SelectedItem.ToString()); //Gibt ein XMLDocument zurück
                dataGridView1.ItemsSource = IInstanzPool.valueDiskIO.loadXMLDocument(IInstanzPool, KatalogComboBox.SelectedItem.ToString());  
            }
    

    Wenn ich das ganze nun Debugge enthält die ItemsSource anschließend mein XMLDocument.

    Wie aber bekomme ich das DataGrid damit nun gefüllt ? Und gibt es Nachteile die Zuweisung in der Codebehind vorzunehmen ?



  • Hallo,

    im Prinzip ist es ja nichts anderes als nen Master-Detail Szenario. Da gibts in der MSDN genügend Beispiele für WPF.

    Sowas was du im SelectionChanged Handler machst, darfst du nicht machen. Du das neuzuweisen der ItemsSource überschreibst du jegliches Binding.

    Desweiteren ist dein XML Schema fürn allerwertesten.
    Mit nem Schema in der Art

    <Fragen>
      <F0>
    ...
      </F0>
      <F1>
    ...
    </F1>
    ...
    

    kann man unmöglich arbeiten, da ja kein einheitlicher Zugriff auf die Unterknoten möglich ist, da alle anders heißen. Nenn die Knoten F0, F1 usw. alle einfach Frage (den bisherigen Frage Knoten tiefer in der Hierachie würd ich irgendwie anders nennen), dann kannst du mit einem XPath Ausdruck auch einfach drauf zugreifen.

    Fürs Databinding egal, aber auch nicht wirklich schön ist der Aufbau von Antworten und RichtigeAnworten. Als erstes das Problem wie oben. Die Knoten müssen alle gleich heißen, sonst kann man damit nicht wirklich gut arbeiten. Desweiteren besteht keine Verbinding zwischen beiden. Zusammengehörige Knoten in Antworten und RichtigeAntworten haben zwar den gleichen Inhalt, haben aber nichts miteinander zu tun und wenn man das einließt hat man auch keine Zusammengehörigkeit. Besser ist es den Antworten ne ID mitzugeben und bei RichtigeAntworten nur noch die IDs der Antworten angeben. Dann ist nämlich die Zuordnung gesichert das ne richtige Antworte auch genau aus der AntwortenListe ist.



  • Okay, das war mir nicht bewusst. Dann sollte das XML File nach diesem Schema aufgebaut sein:

    <?xml version="1.0"?>
    <!--Versionsangabe: V1.0-->
    <Fragenliste>
      <Question>
        <Fachbereich>Backwaren</Fachbereich>
        <Schwierigkeit>leicht</Schwierigkeit>
        <Typ>2</Typ>
        <Feedback>kein Feedback</Feedback>
        <ID>7b29bc76-b541-43b2-9b4f-2dfa57af66dd</ID>
        <Frage>Wie werden Backtriebmittel unterteilt ?</Frage>
        <Antworten>
          <A>biologische Triebmittel<ID>7b29bc76-1</ID></A>
          <A>chemische Triebmittel<ID>7b29bc76-2</ID></A>
          <A>physikalische Triebmittel<ID>7b29bc76-3</ID></A>
          <A>organische Triebmittel<ID>7b29bc76-4</ID></A>
          <A>anorganische Triebmittel<ID>7b29bc76-5</ID></A>
        </Antworten>
        <richtigeAntworten>
          <R>7b29bc76-1</R>
          <R>7b29bc76-2</R>
          <R>7b29bc76-3</R>
        </richtigeAntworten>
        <FrageBild />
        <FeedBackBild />
      </Question>    
    </Fragenliste>
    

    Desweiteren habe ich den SelectionChanged Event Handler rausgenommen, was mir nun auch logisch erscheint.

    Ich würde gerne zumindest einmal hinbekommen, das das obige XML File im DG angezeigt wird, allein schon um DataBindings mal ansatzweise zu verstehen.
    Vor mir liegt ein Nachschlagewerk zur WPF mit über 1000Seiten, wovon ein großes Kapitel den DataBindings gewidmet ist. Nur finde ich nicht den für mich richtigen Ansatz.



  • Okay ... bin nen Schritt weiter:

    <XmlDataProvider x:Key="XMLProvider" Source="C:\Users\Jens\Documents\VanNettenDaten\neu6Fragen.xml" XPath="/Fragenliste/Question" />
    
    <DataGrid HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" SelectionMode="Single" 
                              ColumnWidth="Auto" GridLinesVisibility="Vertical" Margin="4" BorderThickness="0" x:Name="dataGridView1" CanUserAddRows="True" 
                              CanUserDeleteRows="True" AutoGenerateColumns="False" FontSize="9.333" OverridesDefaultStyle="False" IsSynchronizedWithCurrentItem="{x:Null}" ItemsSource="{Binding Source={StaticResource XMLProvider}}">
                        <DataGrid.Columns>
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/Typ}" Header="Typ" IsReadOnly="True"/>
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/Fachbereich}" Header="Fachbereich" IsReadOnly="True" />
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/Schwierigkeit}" Header="Schwierigkeit" IsReadOnly="True" MinWidth="40" />
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/Frage}" Header="Frage" IsReadOnly="True" Width="*" />
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/Antworten}" Header="Antworten" IsReadOnly="True" Width="150" />
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/richtigeAntworten}" Header="richtigeAntworten" IsReadOnly="True" Width="150" />
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/Feedback}" Header="Feedback" IsReadOnly="True" Width="50" />
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/FrageBild}" Header="FrageBild" IsReadOnly="True" Width="50" />
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/FeedBackBild}" Header="FeedBackBild" IsReadOnly="True" Width="50" />
                            <DataGridTextColumn Binding="{Binding XPath=/Fragenliste/Question/ID}" Header="ID" IsReadOnly="True" Width="20" />
                        </DataGrid.Columns>
                    </DataGrid>
    

    Die XML Datei enthält nun zwei Questions im Stammknoten Fragenliste. Es werden in meinem DataGrid auch zwei Zeilen eingerichtet, welche aber die gleichen Daten enthalten.

    Was ist mein Fehler ?



  • Für die, die ebenfalls auf dem Schlauch stehen:

    <?xml version="1.0"?>
    <!--Versionsangabe: DummyVersion-->
    <Fragenliste>
      <Question>
        <Fachbereich>Backwaren</Fachbereich>
        <Schwierigkeit>leicht</Schwierigkeit>
        <Typ>2</Typ>
        <Feedback>kein Feedback</Feedback>
        <ID>7b29bc76-b541-43b2-9b4f-2dfa57af66dd</ID>
        <Frage>Wie werden Backtriebmittel unterteilt ?</Frage>
        <Antworten>
          <A>biologische Triebmittel<AID>70e59ba1-de2f-455e-9071-8835fdee9f1a</AID></A>
          <A>chemische Triebmittel<AID>d28a13a2-3a30-4619-9ce8-1d3094e7bdf0</AID></A>
          <A>physikalische Triebmittel<AID>8d1f958e-39c2-4723-8b3b-e500dd488226</AID></A>
          <A>organische Triebmittel<AID>6337f91b-c612-4caa-82e1-6a6827236e0b</AID></A>
          <A>anorganische Triebmittel<AID>e5f82a0b-1a4b-41bd-b131-b124ae63abad</AID></A>
        </Antworten>
        <richtigeAntworten>
          <R>70e59ba1-de2f-455e-9071-8835fdee9f1a</R>
          <R>d28a13a2-3a30-4619-9ce8-1d3094e7bdf0</R>
          <R>8d1f958e-39c2-4723-8b3b-e500dd488226</R>
        </richtigeAntworten>
        <FrageBild />
        <FeedBackBild />
      </Question>
    
    <DataGrid HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" SelectionMode="Single" 
                		ColumnWidth="Auto" GridLinesVisibility="None" Margin="4,0,4,4" BorderThickness="0" x:Name="dataGridView1" CanUserAddRows="True" 
                		CanUserDeleteRows="True" AutoGenerateColumns="False" FontSize="11" OverridesDefaultStyle="False" IsSynchronizedWithCurrentItem="{x:Null}" ItemsSource="{Binding Source={StaticResource XMLProvider}}" Background="{x:Null}" HeadersVisibility="Column" RowHeight="20">
                		<DataGrid.Columns>
                			<DataGridTextColumn Binding="{Binding XPath=Typ}" Header="Typ" IsReadOnly="True"/>
                			<DataGridTextColumn Binding="{Binding XPath=Fachbereich}" Header="Fachbereich" IsReadOnly="True" />
                			<DataGridTextColumn Binding="{Binding XPath=Schwierigkeit}" Header="Schwierigkeit" IsReadOnly="True" MinWidth="40" />
                			<DataGridTextColumn Binding="{Binding XPath=Frage}" Header="Frage" IsReadOnly="True" Width="*" />
                            <DataGridTextColumn Binding="{Binding XPath=Antworten//child::text()}" Header="Antworten" IsReadOnly="True" Width="150" />
                			<DataGridTextColumn Binding="{Binding XPath=richtigeAntworten}" Header="richtigeAntworten" IsReadOnly="True" Width="150" />
                			<DataGridTextColumn Binding="{Binding XPath=Feedback}" Header="Feedback" IsReadOnly="True" Width="50" />
                			<DataGridTextColumn Binding="{Binding XPath=FrageBild}" Header="FrageBild" IsReadOnly="True" Width="50" />
                			<DataGridTextColumn Binding="{Binding XPath=FeedBackBild}" Header="FeedBackBild" IsReadOnly="True" Width="50" />
                			<DataGridTextColumn Binding="{Binding XPath=ID}" Header="ID" IsReadOnly="True" Width="20" />
                		</DataGrid.Columns>
                	</DataGrid>
    

    Ein kleines Problem dazu habe ich noch, was mich wieder im Aufbau meiner XML Datei verunsichert:

    <DataGridTextColumn Binding="{Binding XPath=Antworten//child::text()}" Header="Antworten" IsReadOnly="True" Width="150" />

    <Antworten>
          <A>biologische Triebmittel<AID>70e59ba1-de2f-455e-9071-8835fdee9f1a</AID></A>
          <A>chemische Triebmittel<AID>d28a13a2-3a30-4619-9ce8-1d3094e7bdf0</AID></A>
          <A>physikalische Triebmittel<AID>8d1f958e-39c2-4723-8b3b-e500dd488226</AID></A>
          <A>organische Triebmittel<AID>6337f91b-c612-4caa-82e1-6a6827236e0b</AID></A>
          <A>anorganische Triebmittel<AID>e5f82a0b-1a4b-41bd-b131-b124ae63abad</AID></A>
        </Antworten>
    

    Bei diesem Code wird mir nur die jeweils erste Antwort im DataGrid angezeigt. Wie kann ich XAML dazu veranlassen mir sämmtliche Antworten anzuzeigen ohne das die AID Nodes angezeigt werden ?

    Bspw. so:

    biologische Triebmittel<!>chemische Triebmittel<!> usw.


Anmelden zum Antworten