【问题标题】:How to programmatically set cell value in DataGridView?如何以编程方式在 DataGridView 中设置单元格值?
【发布时间】:2009-10-04 12:10:27
【问题描述】:

我有一个 DataGridView。一些单元格从串行端口接收数据:我想将数据推送到单元格中,并让它更新底​​层绑定对象。

我正在尝试这样的事情:

SetValueFromSerial (decimal newValue)
{
    dataGridView.CurrentCell.Value = newValue;
}

使用字符串没有帮助:

    dataGridView.CurrentCell.Value = newValue.ToString ();

在这两种情况下,我在网格中都看不到任何东西,并且基础值没有改变。

我用谷歌搜索并在这里搜索,但我没有找到任何东西。 (我可能错过了一些东西,也许是一些显而易见的东西,但我并不是完全懒惰。)

【问题讨论】:

  • 修改cell.Value后调用grid1.NotifyCurrentCellDirty(true);
  • dataGridView.CurrentCell.Value = newValue.ToString (); dataGridView.editingControl.Text = newValue.ToString (); 如果您这样做,您可以立即看到更改。

标签: c# winforms datagridview


【解决方案1】:

如果DataGridView 是数据绑定的,则不应直接修改单元格的内容。相反,您应该修改数据绑定对象。您可以通过DataGridViewRow 的DataBoundItem 访问该对象:

MyObject obj = (MyObject)dataGridView.CurrentRow.DataBoundItem;
obj.MyProperty = newValue;

请注意,绑定对象应该实现INotifyPropertyChanged,以便更改反映在DataGridView中

【讨论】:

  • 我想这个工作的唯一方法是使用 List 作为数据源?这可能不适用于 DataTable 作为数据源?所以我们需要一些 ORM 吗?
  • @user867703,不一定是 List,任何集合都应该有效。如果源是 DataTable,则 DataBoundItem 的类型将为 DataRowView。
  • 一个简单的方法是修改cell.Value后也调用grid1.NotifyCurrentCellDirty(true);
  • 厌倦了这个问题,只有这个对我来说很好。不要忘记在用于绑定的模型类中实现 INotifyPropertyChanged 接口
【解决方案2】:
dataGridView1[1,1].Value="tes";

【讨论】:

    【解决方案3】:

    如果您出于某种原因不想修改数据绑定对象(例如,您想在网格中显示某些视图,但不希望它作为数据源对象的一部分),您可能想要这样做:

    1.手动添加列:

        DataGridViewColumn c = new DataGridViewColumn();
        DataGridViewCell cell = new DataGridViewTextBoxCell();
    
        c.CellTemplate = cell;
        c.HeaderText = "added";
        c.Name = "added";
        c.Visible = true;
    dgv.Columns.Insert(0, c); 
    

    2.在 DataBindingComplete 事件中执行如下操作:

    foreach (DataGridViewRow row in dgv.Rows)
    {if (row.Cells[7].Value.ToString()=="1")
    row.Cells[0].Value = "number one"; }
    

    (只是一个愚蠢的例子)

    但记住它必须在 DataBindingComplete 中,否则值将保持空白

    【讨论】:

      【解决方案4】:

      我搜索了如何插入新行以及如何像 Excel 一样设置其中的单元格的单个值的解决方案。我用以下代码解决了:

      dataGridView1.ReadOnly = false; //Before modifying, it is required.
      dataGridView1.Rows.Add(); //Inserting first row if yet there is no row, first row number is '0'
      dataGridView1.Rows[0].Cells[0].Value = "Razib, this is 0,0!"; //Setting the leftmost and topmost cell's value (Not the column header row!)
      dataGridView1[1, 0].Value = "This is 0,1!"; //Setting the Second cell of the first row!
      

      注意:

      1. 之前我在设计模式下设计了列。
      2. 我已从 datagridview 的属性中将行标题可见性设置为 false。
      3. 最后一行很重要,需要理解: 当你直接给出datagridview的索引时,第一个数字是单元格号,第二个是行号!记住它!

      希望这对你有帮助。

      【讨论】:

        【解决方案5】:

        你还记得refreshdataGridView吗?

        datagridview.refresh();
        

        【讨论】:

          【解决方案6】:

          我遇到了同样的问题 用sql-dataadapter更新数据等

          以下内容对我来说很好

          mydatgridview.Rows[x].Cells[x].Value="test"
          mydatagridview.enabled = false 
          mydatagridview.enabled = true 
          

          【讨论】:

            【解决方案7】:

            试试这个方法:

            dataGridView.CurrentCell.Value = newValue;
            
            dataGridView.EndEdit();
            
            dataGridView.CurrentCell.Value = newValue;
            
            dataGridView.EndEdit();
            

            需要写两次...

            【讨论】:

            • 请解释为什么语句需要写两次?
            【解决方案8】:

            在VB中你可以使用这个

            Dim selectedRow As DataRowView
            selectedRow = dg.Rows(dg.CurrentCell.RowIndex).DataBoundItem
            selectedRow("MyProp") = "myValue"
            dg.NotifyCurrentCellDirty(True)
            

            感谢 saeed serpooshan 最后一排

            【讨论】:

              【解决方案9】:

              以下作品。我可能弄错了,但添加 String 值似乎与 DataGridView 单元格不兼容(尽管我没有尝试或尝试过任何技巧)。

              DataGridViewName.Rows[0].Cells[0].Value = 1;
              

              【讨论】:

                【解决方案10】:

                如果DataGridView 已由DataSource = x 填充(即数据绑定),那么您需要更改绑定数据,而不是DataGridView 单元格本身。

                因此,从已知行或列获取该数据的一种方法是:

                (YourRow.DataBoundItem as DataRowView).Row['YourColumn'] = NewValue;
                

                【讨论】:

                  【解决方案11】:

                  我遇到了同样的问题,并为 VB.NET 解决了以下问题。它是 .NET Framework,因此您应该可以适应。想比较我的解决方案,但现在我发现似乎没有人以我的方式解决它。

                  进行字段声明。

                  Private _currentDataView as DataView

                  因此,遍历所有行并搜索包含我知道在我要更改的单元格旁边的值的单元格对我有用。

                  Public Sub SetCellValue(ByVal value As String)
                      Dim dataView As DataView = _currentDataView
                  
                      For i As Integer = 0 To dataView.Count - 1
                          If dataView(i).Row.Item("projID").ToString.Equals("139") Then
                              dataView(i).Row.Item("Comment") = value
                              Exit For ' Exit early to save performance
                          End If
                      Next
                  End Sub
                  

                  以便您更好地理解它。 我知道 ColumnName "projID" 是 139。我循环直到找到它,然后我可以在我的情况下更改 "ColumnNameofCell" 的值 "Comment"。我将它用于运行时添加的 cmets。

                  【讨论】:

                    【解决方案12】:

                    我尝试了很多方法,唯一有效的是UpdateCellValue:

                    dataGridView.Rows[rowIndex].Cells[columnIndex].Value = "New Value";
                    dataGridView.UpdateCellValue(columnIndex, rowIndex);
                    

                    我希望能有所帮助。 =)

                    【讨论】:

                      【解决方案13】:

                      就像@Thomas 说的,你要改变的元素必须实现 INotifyPropertyChanged。但是,数据源也很重要。它必须是 BindingList,您可以从 List 轻松创建。

                      这是我的示例-数据源首先是DataTable,我将其传输到List,然后创建BindingList。然后我创建 BindingSource 并使用 BindingList 作为 BindingSource 中的 DataSource。最后,DataGridView 中的 DataSource 使用了这个 BindingSource。

                       sp_Select_PersonTableAdapter adapter = new sp_Select_PersonTableAdapter();
                      
                       DataTable tbl = new DataTable();
                       tbl.Merge(adapter.GetData());
                      
                       List<Person> list = tbl.AsEnumerable().Select(x => new Person
                       {
                           Id = (Int32) (x["Id"]),
                           Ime = (string) (x["Name"] ?? ""),
                           Priimek = (string) (x["LastName"] ?? "")
                       }).ToList();
                      
                       BindingList<Person> bindingList = new BindingList<Person>(list);
                      
                       BindingSource bindingSource = new BindingSource();
                       bindingSource.DataSource = bindingList;
                       dgvPerson.DataSource = bindingSource;
                      

                      还有一点很重要:每个类的成员设置器必须调用 OnPropertyChanged()。没有它,它就行不通。所以,我的班级看起来像这样:

                      public class Person : INotifyPropertyChanged
                          {
                              private int _id;
                              private string _name;
                              private string _lastName;
                      
                              public int Id
                              {
                                  get { return _id; }
                                  set
                                  {
                                      if (value != _id)
                                      {
                                          _id = value;
                                          OnPropertyChanged();
                                      }
                                  }
                              }
                              public string Name
                              {
                                  get { return _name; }
                                  set
                                  {
                                      if (value != _name)
                                      {
                                          _name = value;
                                          OnPropertyChanged();
                                      }
                                  }
                              }
                              public string LastName
                              {
                                  get { return _lastName; }
                                  set
                                  {
                                      if (value != _lastName)
                                      {
                                          _lastName= value;
                                          OnPropertyChanged();
                                      }
                                  }
                              }
                              public event PropertyChangedEventHandler PropertyChanged;
                      
                              [NotifyPropertyChangedInvocator]
                              protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
                              {
                                  PropertyChangedEventHandler handler = PropertyChanged;
                                  if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
                              }
                      
                          }
                      

                      有关此主题的更多信息:http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx

                      【讨论】:

                        【解决方案14】:
                        private void btn_Addtoreciept_Click(object sender, EventArgs e)
                        {            
                            serial_number++;
                            dataGridView_inventory.Rows[serial_number - 1].Cells[0].Value = serial_number;
                            dataGridView_inventory.Rows[serial_number - 1].Cells[1].Value =comboBox_Reciept_name.Text;
                            dataGridView_inventory.Rows[serial_number - 1].Cells[2].Value = numericUpDown_recieptprice.Value;
                            dataGridView_inventory.Rows[serial_number - 1].Cells[3].Value = numericUpDown_Recieptpieces.Value;
                            dataGridView_inventory.Rows[serial_number - 1].Cells[4].Value = numericUpDown_recieptprice.Value * numericUpDown_Recieptpieces.Value;
                            numericUpDown_RecieptTotal.Value = serial_number;
                        }
                        

                        第一次很顺利,但第二次按它给我错误 “索引超出范围。必须为非负数且小于集合的大小。 参数名称:索引“但是当我点击单元格时会出现另一行,然后它适用于下一行,然后继续......

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2019-04-09
                          • 1970-01-01
                          • 1970-01-01
                          • 2010-12-21
                          • 2015-04-27
                          相关资源
                          最近更新 更多