如何将XML数据导入DataGrid

时间:2019-08-04 11:14:44

标签: c# wpf data-binding datagrid

我是c#的新手,它试图将XML文件导入到DataGrid中,但是到目前为止,我设法只导入了列标头,而没有导入节点内的数据。我不知道在运行时会从xml加载什么样的数据,它可以是任何东西,但是下面的示例是所有内容的总体结构。

我试图为我的问题寻找答案,但是我得到的一切都是针对我不在这里使用的DataGridView,所以所有搜索都比我想要的要多。任何帮助将不胜感激。标签的深度可以从1到40甚至更多。

我的XMLdata看起来像这样:

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

我的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>

我的导入代码

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,
                });
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

最简单的方法是使用LINQ to XML。您可以将XElement直接绑定到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>