简体   繁体   中英

How to import XML data into DataGrid

I'm new to c# and trying to inport a XML file into DataGrid but so far I managed to import only the columns header but not the data inside the nodes. I will not know at runtime what kind of data will be loaded from the xml it can be anything but the example below is the overall structure that everything follows.

I have tried looking for answers for my problem but everything I get is for DataGridView which I am not using here so all the searches came up with more information about that than what I am looking to do. Any help will be greatly appriciated. The depth of the tags can very from 1 to 40 or more.

My XMLdata looks like this:

<Details>
 <Record>
  <Username>name</Username>
  <FirstName>firstname</FirstName>
  <LastName>lastname</LastName>
  etc
   .
   .
   .
 </Record>
</Details>

My Xaml

<DataGrid x:Name="DetailsGridTemplate" AlternatingRowBackground="AliceBlue" CanUserAddRows="True" CanUserDeleteRows="True"
          ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible"
          Height="380" Width="430" AutoGenerateColumns="False" IsReadOnly="True" Grid.ColumnSpan="2" Margin="0,0,0.4,0"
          ItemsSource="{Binding}">
</DataGrid>

My import code

private void InitGridFromXML(string xmlPath)
{
    var data = XElement.Load(xmlPath);

    // Set Grid data to row nodes (NOTE: grid = DataGrid member)
    var elements = data.Elements("Item");
    DetailsGridTemplate.ItemsSource = elements;

    // Create grid columns from node attributes.  A hashtable ensures
    // only one column per attribute since this iterates through all
    // attributes in all nodes.  This way, the grid can handle nodes with
    // mutually different attribute sets.
    var cols = new Hashtable();
    var rows = new Hashtable();
    foreach (XElement node in data.Descendants("Item"))
    {
        foreach (XElement childNode in node.Descendants())
        {
            var col = childNode.Name.LocalName;
            var row = childNode.Value; 

            // Only add col if it wasn't added before
            if (!cols.Contains(col))
            {
                // Mark col as added
                cols[col] = true;
                rows[row] = true;
                // Add a column with the title of the attribute and bind to its
                // value
                DetailsGridTemplate.Columns.Add(new DataGridTextColumn
                {
                    Header = col,

                });
                DetailsGridTemplate.Items.Add(new DataGridRow
                {
                    DataContext = row,
                });
            }
        }
    }
}

Easiest is to use LINQ to XML . You can bind an XElement directly to an ItemsSource .

ViewModel.cs

public class ViewModel : INotifyPropertyChanged
{
  public ViewModel()
  {
    this.DataTable = new DataTable();
  }

  private void InitGridFromXML(string xmlPath)
  {
    var xmlEntities = XElement.Load(xmlPath).Elements().ToList();
    var dataTable = new DataTable();
    dataTable.Columns.AddRange(
      xmlEntities
        .FirstOrDefault()?
        .Elements()
        .Select(node => new DataColumn(node.Name.LocalName))
        .ToArray());

    foreach (XElement xElement in xmlEntities)
    {
      dataTable.Rows.Add(
        xElement.Elements()
          .Select(node => node.Value)
          .ToArray());
    }

    this.DataTable = dataTable;
  }

  private DataTable dataTable;  
  public DataTable DataTable
  {
    get => this.dataTable;
    set
    {
      this.dataTable = value; 
      OnPropertyChanged();
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

MainWindow.xaml

<Window>
  <Window.DataContext>
    <ViewModel />
  </Window.DataContext>

  <Grid>
    <DataGrid AutoGenerateColumns="True"
              ItemsSource="{Binding DataTable}" />
  <Grid>
<Window>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM