Member 9940802 Ответов: 1

DataGridViewComboBoxCell не работает правильно


У меня есть очень простой пример приложения ниже. Это относится к Windows Forms и должно иметь соответствие для созданного в конструкторе с DataGridView, который имеет два столбца: имя и отдел. Отдел-это DataGridViewComboBoxCell.

В таблице перечислены данные, как и ожидалось, а в поле со списком перечислены его элементы, как и ожидалось. Однако я не могу получить данные, выбранные в поле со списком, привязанным к элементу DataBoundItem сетки. Например, при первом запуске приложения Мой единственный объект Person имеет DepartmentID = 2, который соответствует значению в поле со списком, но в поле со списком ничего не выбрано. Когда что-то выбрано в поле со списком, оно не отражается в объекте Person.

Существует закомментированная строка кода для установки ValueMember, но это вызывает ошибку "поле с именем DeptID не существует".

Важно, чтобы оба набора данных были ArrayList и не DataTable.

Как завершить привязку между строковыми данными и выбором поля со списком?

--- Полный код проекта приведен ниже ---

using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace TestApp
{
	public partial class Form1 : Form
	{
		private ArrayList personList = new ArrayList();
		private ArrayList deptList = new ArrayList();
		BindingSource m_BindSource = new BindingSource();
		public Form1()
		{
			InitializeComponent();
		}
		private void Form1_Load(object sender, EventArgs e)
		{
			personList.Add(new Person("Tim", 2));
			deptList.Add(new Department("A", 1));
			deptList.Add(new Department("B", 2));
			deptList.Add(new Department("C", 3));
			DataGridViewComboBoxCell cell = (DataGridViewComboBoxCell)grid1.Columns[1].CellTemplate;
			cell.DataSource = deptList;
			cell.DisplayMember = "DeptName";
			//cell.ValueMember = "DeptID";	// "Field called DeptID does not exist"
			try
			{
				m_BindSource.DataSource = null;
				m_BindSource.DataSource = personList;
				grid1.DataSource = m_BindSource;
			}
			catch (Exception ex)
			{
				ex.GetType();
				MessageBox.Show(ex.Message);
			}
		}
	}
	public class Person
	{
		public Person(String name, int deptID)
		{
			PersonName = name;
			DepartmentID = deptID;
		}
		private String m_PersonName;
		public String PersonName
		{
			get { return m_PersonName; }
			set { m_PersonName = value; }
		}
		private int m_DepartmentID;
		public int DepartmentID
		{
			get { return m_DepartmentID; }
			set { m_DepartmentID = value; }
		}
	}
	public class Department
	{
		public Department(String name, int deptID)
		{
			DeptName = name;
			DepartmentID = deptID;
		}
		private String m_DeptName;
		public String DeptName
		{
			get { return m_DeptName; }
			set { m_DeptName = value; }
		}
		private int m_DepartmentID;
		public int DepartmentID
		{
			get { return m_DepartmentID; }
			set { m_DepartmentID = value; }
		}
	}
}

Sergey Alexandrovich Kryukov

Просто примечание: никогда не используйте ArrayList в новой разработке, всегда используйте System.Коллекции.Универсальный.Список< и GT;
—СА

1 Ответов

Рейтинг:
7

Member 9940802

После долгих поисков и переделок я нашел решение. Ниже приведено тело функции Form1_Load (), которая работает. Решение состоит из двух частей:

1) вместо того чтобы создавать ячейку/столбец на лету, просто встроите его в представление времени разработки и соответствующим образом свяжите, как показано ниже оператора catch()

2) сетка не будет автоматически сопоставлять данные строк с данными combobox, как я привык. Цикл for В конце проходит через него и связывает существующий выбор данных строки с соответствующей записью в выпадающем списке.

В качестве дополнительного замечания я обнаружил, что это решение имеет дополнительные проблемы, если DataGridView находится в элементе управления tab. Если сетка находится на любой вкладке, отличной от первой, привязка строки/выпадающего списка завершится неудачно. Является ли это ошибкой MS или нет, я не знаю, но решение состояло в том, чтобы поместить цикл for в код ниже в событии SelectedIndexChanged() для элемента управления tab и запустить его при переходе на соответствующую вкладку.

personList.Add(new Person("Tim", 2));   // Create one Person data object and add it to the list used by the DataGridView

// Create a list of Departments to be used by the combo box in the DataGridView
deptList.Add(new Department("A", 1));
deptList.Add(new Department("B", 2));
deptList.Add(new Department("C", 3));

grid1.AutoGenerateColumns = false;  // If we don't do this, the DepartmentID shows up as an additional column

try // Bind the Person list to the DataGridView
{
    m_BindSource.DataSource = null;
    m_BindSource.DataSource = personList;
    grid1.DataSource = m_BindSource;
}
catch (Exception ex)
{
    ex.GetType();
    MessageBox.Show(ex.Message);
}

// Bind the Department data to the appropriate column in the DataGridView
((DataGridViewComboBoxColumn)grid1.Columns["Department"]).DataSource = deptList;
((DataGridViewComboBoxColumn)grid1.Columns["Department"]).DisplayMember = "DeptName";
((DataGridViewComboBoxColumn)grid1.Columns["Department"]).ValueMember = "DeptID";

// Since the DataGridView won't automatically sync the Department list with each Person's DepartmentID, we have to manually link the two. This is what
// causes the combo box to show the proper selection for each Person's Department in the grid of existing data.
foreach (DataGridViewRow row in grid1.Rows)
{
    if (row.DataBoundItem != null)
    {
        row.Cells["Department"].Value = ((Person)row.DataBoundItem).DepartmentID;
    }
}


Member 13847218

как вставить приложения Windows на C# текстовое поле значения то же значение Нет сохранить SQL