it-roy-ru.com

Как программно установить значение ячейки в DataGridView?

У меня есть DataGridView. Некоторые из ячеек получают свои данные от последовательного порта: я хочу поместить данные в ячейку и обновить их базовый связанный объект.

Я пытаюсь что-то вроде этого:

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

использование строки не помогает:

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

В обоих случаях я ничего не вижу в сетке, и базовое значение не изменяется.

Я сделал Google и поиск здесь, но я ничего не нашел. (Возможно, я что-то пропустил, возможно, что-то очевидное, но я не совершенно ленивый.)

35
XXXXX

Если DataGridView привязан к данным, вам не следует напрямую изменять содержимое ячейки. Вместо этого вы должны изменить объект с привязкой к данным. Вы можете получить доступ к этому объекту через DataBoundItemDataGridViewRow:

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

Обратите внимание, что связанный объект должен реализовывать INotifyPropertyChanged, чтобы изменение отражалось в DataGridView

33
Thomas Levesque
dataGridView1[1,1].Value="tes";
28
arced

Если вы по какой-то причине не хотите изменять объект, привязанный к базе данных (например, вы хотите отобразить какой-либо вид в вашей сетке, но не хотите, чтобы он был частью объекта источника данных), вы можете сделать это:

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, иначе значение останется пустым

5
BornToCode

У меня была такая же проблема С sql-dataadapter для обновления данных и так далее 

следующее работает у меня нормально

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

Я искал решение, как я могу вставить новую строку и Как установить отдельные значения ячеек внутри него, как 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. Я установил видимость заголовка строки в false из свойства datagridview.
  3. Последняя строка важна для понимания: Когда вы непосредственно указываете индекс сетки данных, первое число - это номер ячейки, второе - номер строки! Помни это!

Надеюсь, это поможет вам.

4
Razib Ali

Вы помните, чтобы обновить dataGridView?

datagridview.refresh();
4
Graviton

Попробуйте так:

dataGridView.CurrentCell.Value = newValue;

dataGridView.EndEdit();

dataGridView.CurrentCell.Value = newValue;

dataGridView.EndEdit();

Нужно написать два раза ...

3
Vytautas Jakstys

Я столкнулся с той же проблемой и решил ее следующим образом для 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" в моем случае "Комментарий". Я использую это для комментариев, добавленных во время выполнения.

 dataview

1
Matthis Kohli

Если DataGridView заполнен DataSource = x (то есть привязан к данным), вам нужно изменить связанные данные , а не сами ячейки DataGridView. 

Таким образом, один из способов получить эти данные из известной строки или столбца:

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

в VB вы можете использовать этот 

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

спасибо Саиду Серпоошану за последний ряд

1
Eric Draven

Следующие работы. Я могу ошибаться, но добавление значения String кажется несовместимым с ячейкой DataGridView (хотя я не экспериментировал и не пробовал какие-либо хаки).

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

Я перепробовал много методов, и единственный, который работал, был UpdateCellValue:

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

Я надеюсь, что помог. знак равно

0
gamendola
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;
}

в первый раз все идет хорошо, но нажатие во второй раз вызывает ошибку "Индекс был вне диапазона. Должен быть неотрицательным и меньше размера коллекции . Имя параметра: индекс", но когда я нажимаю в ячейке появляется другой ряд, а затем он работает для следующего ряда, и продолжить ... 

0
Asif Ali

Как сказал @Thomas, элемент, который вы хотите изменить, должен реализовывать INotifyPropertyChanged. Но источник данных также важен. Это должен быть BindingList, который вы можете легко создать из List.

Вот мой пример - источником данных является сначала DataTable, который я передаю в List, а затем создаю BindingList. Затем я создаю BindingSource и использую BindingList в качестве источника данных из BindingSource. Наконец, DataSource из DataGridView использует этот 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

0
FrenkyB