2009-01-28 81 views
4

我有一个从CSV文件填充的DataTable,然后使用DataGridView在内存中编辑数据。据我所知,数据的编程编辑应该在用户编辑通过的DataTable上完成。 DataGridView。将列添加到绑定到DataGridView的DataTable不会更新视图

但是,当我以编程方式向DataTable添加列时,它不会自动反映在DataGridView中,我怀疑反过来也是如此。

你如何保持两个并发?我认为数据绑定是,这是自动的想法...

下面是相关设置代码 - WorksheetGridViewDataGridView


// Can access data directly 
public DataTable data = new DataTable(); 

public WorksheetGridView() 
{ 
    InitializeComponent(); 

    // Allow copying from table to clipboard 
    this.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText; 

    // TODO: how to allow both row and column selects? 
    //this.SelectionMode = DataGridViewSelectionMode.ColumnHeaderSelect; 

    // Load up a blank DataTable to hold user inputted data 
    int i; 
    const int numBlankRows = Config.Application.DefaultNumRows; 
    const int numBlankCols = Config.Application.DefaultNumCols; 
    // TODO: Figure out how to include this as a config variable 
    DBNull dfltCellContent = DBNull.Value; 
    DataRow tmpRow; 
    // Add columns - i used for naming 
    for (i = 0; i < numBlankCols; i++) 
    { 
     this.AddColumn(i); 
    } 

    // Add rows 
    for (i = 0; i < numBlankRows; i++) 
    { 
     tmpRow = this.data.NewRow(); 
     // Fill cells with something (i.e. blank cells) 
     foreach (DataColumn col in this.data.Columns) 
     { 
      tmpRow[col.ColumnName] = DBNull.Value; 
     } 
     this.data.Rows.Add(tmpRow); 
    } 
    // Link data to the view 
    this.DataSource = this.data; 
} 

private void AddColumn(int colIndex) 
{ 
    // Adds a column to the data array 
    DataColumn tmpCol; 
    tmpCol = new DataColumn(); 
    tmpCol.DataType = Type.GetType(Config.Application.DataType); 
    tmpCol.ColumnName = "C" + colIndex.ToString(); 
    tmpCol.ReadOnly = false; 
    tmpCol.Unique = false; 
    tmpCol.AllowDBNull = true; 
    this.data.Columns.Add(tmpCol); 
} 

不起作用该位后,当我打电话AddColumn为在这个代码中的实例来处理粘贴制表符分隔的数据,


     public void PasteToCells(string mode) 
     { 
      // TODO: Write paste code 
      int i; 
      if (Clipboard.ContainsText()) 
      { 
       string clipBoardContent = Clipboard.GetText(); 
       using (CsvReader pastedCsvReader = new CsvReader(
        new StringReader(clipBoardContent), false, '\t')) 
       { 
        // TODO: If more rows/cols than in data table then expand accordingly 
        int numPastedCols = pastedCsvReader.FieldCount; 
        int currRowIndex, currColumnIndex; 
        GetSelectedInsertPoint(out currRowIndex, out currColumnIndex); 
        // Make space for columns if needed 
        if (mode == "insertcols") 
        { 
         int baseIndex = this.data.Columns.Count; 
         for (i = 0; i < numPastedCols; i++) 
         { 
          //this.Columns.Add 
          // TODO: Doesn't work yet - do you edit the DataGridView and reflect to DataTable or vise-versa? 
          this.AddColumn(baseIndex + i); 

         } 
        } 
        while (pastedCsvReader.ReadNextRecord()) 
        { 
         // Make space for rows (row by row) if needed 
         if (mode == "insertrows") 
         { 
          this.data.NewRow(); 
          // TODO: Add a row 
         } 
         // Populate the cells with valid pasted text 
         for (i = 0; i < numPastedCols; i++) 
         { 
          this.data.Rows[currRowIndex][currColumnIndex + i] = ConvertCellContent(pastedCsvReader[i]); 
         } 
         currRowIndex = currRowIndex + 1; 

        } 



       } 

      } 
      else 
      { 
       // TODO: Do nothing? 
       Console.WriteLine("No text on clipboard"); 
      } 
     } 

我试过下面给出的例子,它的工作。但是,当我尝试执行此操作时,水平滚动条会短暂​​扩展并收缩,但子类型DataGridView中的表未更新。不过,该列在DataTable之间 - 例如,我无法添加同名的列,列数也反映了额外的列。有没有设计者可能会限制更新DataGridView

另外添加行工作正常。

解决:

AutoGeneratedColumns被设置为在设计代码false尽管是在属性对话框true(和在代码中明确设置)。最初的列是以编程方式生成的,所以不应该出现,但是由于设计器代码还继续生成最初用于调试的“设计为”列,因此未能提供。

道德:检查自动生成的代码!

除此之外,看this postthis post

回答

2

这听起来不对。为了测试它,我编写了一个简单的应用程序,它创建了一个DataTable并向其中添加了一些数据。在button1上单击它将表绑定到DataGridView。然后,我添加了第二个按钮,单击它时,将另一列添加到基础DataTable。当我测试它时,我点击第二个按钮,网格immedialtey反映了更新。为了测试相反的结果,我添加了第三个按钮,弹出一个对话框,其中包含绑定到相同数据表的DataGridView。在运行时,我向第一个datagridview添加了一些值,当我点击按钮来调出对话框时,所做的更改就会反映出来。

我的观点是,他们应该保持并发。当Mark建议您检查AutoGenerateColumns是否设置为true时,Mark可能是对的。你不需要调用DataBind,这只适用于Web上的GridView。也许你可以张贴你在做什么,因为这应该工作。

我如何测试它:

 DataTable table = new DataTable(); 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      table.Columns.Add("Name"); 
      table.Columns.Add("Age", typeof(int)); 
      table.Rows.Add("Alex", 26); 
      table.Rows.Add("Jim", 36); 
      table.Rows.Add("Bob", 34); 
      table.Rows.Add("Mike", 47); 
      table.Rows.Add("Joe", 61); 

      this.dataGridView1.DataSource = table; 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      table.Columns.Add("Height", typeof(int)); 
      foreach (DataRow row in table.Rows) 
      { 
       row["Height"] = 100; 
      } 
     } 

     private void button3_Click(object sender, EventArgs e) 
     { 
      GridViewer g = new GridViewer { DataSource = table }; 
      g.ShowDialog(); 
     } 

     public partial class GridViewer : Form //just has a DataGridView on it 
     { 
      public GridViewer() 
      { 
      InitializeComponent(); 
      } 

      public object DataSource 
      { 
       get { return this.dataGridView1.DataSource; } 
       set { this.dataGridView1.DataSource = value; } 
      } 
     } 
+0

特别是检查设计器代码中的AutoGenerateColumns值。由于该示例在调试中帮助了很多人,因此选择了答案! – Brendan 2009-01-31 16:29:29

1

是的AutoGenerateColumns设置为true?如果您在初始绑定后进行更改,则还必须调用DataBind()以重新绑定已更改的数据源。我知道这对于AJAX回调是正确的,我想认为这对于WinForms控件PostBack来说是正确的。

+0

的AutoGenerateColumns是真的 – Brendan 2009-01-29 20:09:05

-1

我有同样的问题,我发布了的DataBind()。这不是所有事情的灵丹妙药,但是在少数情况下,这是帮助我的。我不得不把它通过一个数据视图捕获信息,将EditItemIndex声明后,立即EditCommand和更新命令事件前后,

protected void datalistUWSolutions_EditCommand(object source, DataListCommandEventArgs e) 
{ 
    datalistUWSolutions.EditItemIndex = e.Item.ItemIndex; 
    datalistUWSolutions.DataBind(); // refresh the grid. 
} 

protected void datalistUWSolutions_UpdateCommand(object source, DataListCommandEventArgs e) 
{ 
    objDSSolutions.UpdateParameters["Name"].DefaultValue = ((Label)e.Item.FindControl("lblSolutionName")).Text; 
    objDSSolutions.UpdateParameters["PriorityOrder"].DefaultValue = ((Label)e.Item.FindControl("lblOrder")).Text; 
    objDSSolutions.UpdateParameters["Value"].DefaultValue = ((TextBox)e.Item.FindControl("txtSolutionValue")).Text; 
    objDSSolutions.Update(); 
    datalistUWSolutions.EditItemIndex = -1; // Release the edited record 
    datalistUWSolutions.DataBind();   // Redind the records for refesh the control 
} 
+0

属于System.Windows.Forms一部分的DataGridView没有DataBind方法。你正在考虑的是GridView,它是System.Web.UI.WebControls的一部分。 OP在谈论WinForms。 – BFree 2009-01-28 22:43:18

1

这里是你不需要指定另一个解决方案数据网格的“名称”,以便数据网格可以是模板元素。

(在我的情况下,数据网格里面TabControl.ContentTemplate模板元素)

以显示新的列(在最初的结合编程方式添加)的关键是迫使DataGrid中刷新。 从Force WPF DataGrid to regenerate itself的答案中,Andres建议将AutoGenerateColumns从false设置为true将强制datagrid刷新。

这意味着我只需要:

  1. 绑定AutoGenerateColumns到我的对象
  2. 的属性格式设置为false的属性添加列之前
  3. 设置添加列后的属性格式设置为true。

下面是代码:

XAML:

<DataGrid AutoGenerateColumns="{Binding toggleToRefresh}" 
      ItemsSource="{Binding dataTable}" 
      /> 

C#:

public class MyTabItem : ObservableObject 
{ 
     private DataTable _dataTable = new DataTable(); 
     public DataTable dataTable 
     { 
      get { return _dataTable; } 
     } 

     private bool _toggleToRefresh = true; 
     public bool toggleToRefresh 
     { 
      get { return _toggleToRefresh; } 
      set 
      { 
       if (_toggleToRefresh != value) 
       { 
        _toggleToRefresh = value; 
        RaisePropertyChanged("toggleToRefresh"); 
       } 
      } 
     } 

     public void addDTColumn() 
     { 
      toggleToRefresh = false; 
      string newColumnName = "x" + dataTable.Columns.Count.ToString(); 
      dataTable.Columns.Add(newColumnName, typeof(double)); 
      foreach (DataRow row in dataTable.Rows) 
      { 
       row[newColumnName] = 0.0; 
      } 
      toggleToRefresh = true; 
     } 

     public void addDTRow() 
     { 
      var row = dataTable.NewRow(); 
      foreach (DataColumn col in dataTable.Columns) 
      { 
       row[col.ColumnName] = 0.0; 
      } 
      dataTable.Rows.Add(row); 
     } 
} 

希望这有助于:)

相关问题