2015-08-11 6 views
1

Для одного из моих проектов я пытаюсь загрузить данные из файла (например, * .csv) и отобразить его в DataGrid. Формат файла не указан. Например, количество столбцов и строк отличается от файла к файлу. Поэтому задача состоит в том, чтобы загрузить общую таблицу данных в программу и просмотреть ее в DataGrid.Связывание данных Wpf DataGrid с произвольными столбцами и строками

Моей первой попыткой было использовать DataTable и связать его как-то с DataGrid. Однако после некоторого времени поиска я прочитал, что использование DataTable - не лучшее решение, и вместо этого следует использовать модели данных. К сожалению, большинство примеров в Интернете используют данные с фиксированными столбцами данных. Кроме того, я не смог получить привязку между DataGrid и DataTable для правильной работы. Было бы очень приятно иметь возможность вносить изменения в данные на обоих концах: DataGrid (как пользователь) и базовую структуру данных (как и код).

Пожалуйста, может кто-нибудь объяснить, почему DataTable не должен использоваться? Что следует использовать вместо этого для достижения вышеуказанного поведения?

Загрузка самой информации не должна быть проблемой, но как хранить, обрабатывать и связывать таблицу данных гибким способом с DataGrid.

Следующий код вид работ. Однако, похоже, он не реагирует на какие-либо изменения в данных, например, добавление строк или столбцов, но DataTable содержит правильные данные.

<DataGrid x:Name="myDataGrid" AutoGenerateColumns="True" 
x:Name="myDataGrid1" AutoGenerateColumns="True" ItemsSource="{Binding myDataTable}" /> 
DataTable myDataTable { get; private set; } 
... 
myDataGrid.DataContext = this; 
LoadData(); 
myDataGrid.ItemsSource = myDataTable.DefaultView; 

Я очень признателен за любую помощь! Заранее спасибо!

+0

вы проверить: http://stackoverflow.com/questions/17915840/binding-a-wpf-datagrid-to-a-datatable? –

+0

Спасибо за ваш ответ. Решение, представленное в этой теме, фактически совпадает с моим «примером». Это нормально, если содержимое ячеек изменяется, но не удается, если строки или столбцы меняются ... – Chocko

ответ

0

После нескольких дальнейших исследований я нашел решение, которое подходит для меня. Тем не менее, он чувствует себя немного странным и не лучшим решением, но я могу жить с этим. Еще раз спасибо за ваши усилия, которые мне очень помогли.

Идея состоит в том, чтобы обновить GridView всякий раз, когда колонка добавила/удалила с помощью unset/установила DataContext из GridView. Для достижения этого я использую событие DataTable.Columns.CollectionChanged.

Теперь почти все в порядке. Единственная проблема, которая остается, - это когда новая строка добавляется пользователем через GridView (при нажатии в последней пустой строке и введите данные). Тем не менее, это лишь незначительная проблема, так как связанная DataTable обновляется правильно, и только второй GridView (в приведенном ниже примере) отображается неправильно.

Вопрос остается, является ли использование DataTable лучшим решением.Если переустановка из DataContext вызывает проблемы для больших наборов данных должны быть проверены ...

Вот полный пример по этому вопросу и решения:

XAML:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     x:Class="WpfApplicationTest.MainWindow" 
     Title="DataGrid and DataTable Test" Height="500" Width="800"> 
    <DockPanel> 
     <StackPanel Orientation="Horizontal" DockPanel.Dock="Top"> 
      <Button Click="ButtonRefresh_Click">Refresh Grids</Button> 
      <Button Click="ButtonAddRow_Click">Add Row</Button> 
      <Button Click="ButtonAddCol_Click">Add Col</Button> 
      <Button Click="ButtonEdit_Click">Edit Randomly</Button> 
     </StackPanel> 
     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*"/> 
       <ColumnDefinition Width="*"/> 
      </Grid.ColumnDefinitions> 
      <DataGrid x:Name="myDataGrid0" Grid.Column="0" AutoGenerateColumns="True" ItemsSource="{Binding}" /> 
      <DataGrid x:Name="myDataGrid1" Grid.Column="1" AutoGenerateColumns="True" ItemsSource="{Binding}" /> 
     </Grid> 
    </DockPanel> 
</Window> 

Code Behind :

using System; 
using System.Data; 
using System.Windows; 

namespace WpfApplicationTest 
{ 
    public partial class MainWindow : Window 
    { 
     private DataTable myDataTable; 
     private Random myRandom = new Random(); 

     public MainWindow() 
     { 
      InitializeComponent(); 

      myDataTable = new DataTable(); 

      // create some datatable 
      myDataTable.Columns.Add("First"); 
      myDataTable.Columns.Add("Second"); 
      myDataTable.Rows.Add(myRandom.Next(100).ToString(), myRandom.Next(100).ToString()); 
      myDataTable.Rows.Add(myRandom.Next(100).ToString(), myRandom.Next(100).ToString()); 

      myDataGrid0.DataContext = myDataTable; 
      myDataGrid1.DataContext = myDataTable; 

      myDataTable.Columns.CollectionChanged += Columns_CollectionChanged; 
     } 

     private void Columns_CollectionChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e) 
     { 
      // refresh the grid views by reseting the data context after the columns have changed 
      myDataGrid0.DataContext = null; 
      myDataGrid0.DataContext = myDataTable; 
      myDataGrid1.DataContext = null; 
      myDataGrid1.DataContext = myDataTable; 
     } 

     private void ButtonRefresh_Click(object sender, RoutedEventArgs e) 
     { 
      // refresh the grid views by reseting the data context 
      myDataGrid0.DataContext = null; 
      myDataGrid0.DataContext = myDataTable; 
      myDataGrid1.DataContext = null; 
      myDataGrid1.DataContext = myDataTable; 
     } 

     private void ButtonAddRow_Click(object sender, RoutedEventArgs e) 
     { 
      // add rows with random content 
      DataRow row = myDataTable.NewRow(); 
      for (int i = 0; i < row.ItemArray.Length; ++i) 
       row[i] = myRandom.Next(100); 
      myDataTable.Rows.Add(row); 
     } 

     int rowcount = 0; 
     private void ButtonAddCol_Click(object sender, RoutedEventArgs e) 
     { 
      // add columns with random content 
      myDataTable.Columns.Add("New" + rowcount.ToString()); 
      foreach (DataRow row in myDataTable.Rows) 
       row["New" + rowcount.ToString()] = myRandom.Next(100); 
      ++rowcount; 
     } 

     private void ButtonEdit_Click(object sender, RoutedEventArgs e) 
     { 
      // randomly change some data table values 
      myDataTable.Rows[myRandom.Next(myDataTable.Rows.Count)][myRandom.Next(myDataTable.Columns.Count)] = myRandom.Next(100); 
     } 
    } 
} 
0

Попробуйте установить ItemsSource на BindingListCollectionView. До сих пор мне повезло. Я использую эти методы расширения:

public static BindingListCollectionView GetCollectionView(this DataTable table) 
     { 
      return new BindingListCollectionView(table.DefaultView); 
     } 



public static DataTable GetDataTable(this BindingListCollectionView view) 
    { 
     var dataView = view.SourceCollection as DataView; 
     if (dataView != null) 
     { 
      return dataView.Table; 
     } 

     return null; 
    } 

использовать его в коде, как:

myDataGrid.ItemsSource = myDataTable.GetCollectionView(); 

и

var view = myDataGrid.ItemsSource as BindingListCollectionView; 
var table = view.GetDataTable(); 

Вы должны быть в состоянии использовать DataTable объект, как вы обычно делаете со всеми изменений, сохраненных сеткой.

+0

Спасибо за ваше предложение. Но использование 'BindingListCollectionView' вместо' DataTable' (или 'DataTable.DefaulView') для привязки не имело никакого значения ... – Chocko

Смежные вопросы