DataGridViewComboBoxColumn, будь он неладен
От: karapetyan_ashot  
Дата: 23.09.08 14:40
Оценка:
Народ, 2 сутки ломаю голову...........
Как в DataGridViewComboBoxColumn запихнуть null, если колонка таблицы типа integer?
именно типа integer, а не string. потому что если string я могу это сделать.

специально для сего вопроса набросал пример:
там DataGridView с 4 колонками, 2 из которых отображают данные из одной колонки таблицы ( Type )
причем одна типа DataGridViewTextBoxColumn, а другая DataGridViewComboBoxColumn.
так вот в текстовое поле я могу вставить NULL, (скорее DBNull.Value) просто написав <NULL> либо нажав <Ctrl>+<0>.
а в комбобоксе при выборе -неизвестно- вставляется не null a -1, а при нажатии <Ctrl>+<0>, вообше вылетает ошибка System.FormatException.

вот пример:

using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace GridComboForForum
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.Run(new MyTestForm());
        }
    }

    class MyTestForm : Form
    {
        DataTable _table;
        DataGridView _grid;

        public MyTestForm()
        {
            this.Load += new EventHandler(frmExp_Load);
        }

        void frmExp_Load(object sender, EventArgs e)
        {
            this.Text = "Test form";
            this.Width = 640;
            this.Height = 300;

            this.CreateTable();
            this.FillData();
            this.CreateGrid();
        }


        private void CreateGrid()
        {
            // сам грид
            this._grid = new DataGridView();
            this._grid.Width = 610;
            this._grid.Height = 250;
            this._grid.Location = new System.Drawing.Point(10, 10);
            this._grid.AutoGenerateColumns = false;
            this._grid.AllowUserToAddRows = false;

            // колонки
            // ID
            DataGridViewTextBoxColumn colID = new DataGridViewTextBoxColumn();
            colID.DataPropertyName = "ID";
            colID.HeaderText = "ID";
            colID.Width = 50;
            this._grid.Columns.Add(colID);

            // Type: вот тут я сделал 2 колонки грида связанные с одной колонкой таблицы : type
            // первая колонка - текстовая, тут все понятно и все работает.
            DataGridViewTextBoxColumn colTypeTxt = new DataGridViewTextBoxColumn();
            colTypeTxt.DataPropertyName = "Type";
            colTypeTxt.HeaderText = "Type (textbox)";
            colTypeTxt.DefaultCellStyle.NullValue = "<NULL>";
            colTypeTxt.ValueType = typeof(int);
            this._grid.Columns.Add(colTypeTxt);

            // а вот здесь "камень преткновения" комбобокс!!!
            DataGridViewComboBoxColumn colTypeCombo = new DataGridViewComboBoxColumn();
            colTypeCombo.DataPropertyName = "Type";
            colTypeCombo.HeaderText = "Type (combobox)";
            colTypeCombo.Width = 150;

            colTypeCombo.DefaultCellStyle.NullValue = "-1";

            colTypeCombo.Items.Add(new TypeItem(-1, "-неизвестно-"));
            colTypeCombo.Items.Add(new TypeItem(1, "блондин"));
            colTypeCombo.Items.Add(new TypeItem(2, "брюнет"));
            colTypeCombo.Items.Add(new TypeItem(3, "шатен"));

            colTypeCombo.DisplayMember = "Name";
            colTypeCombo.ValueMember = "ID";

            this._grid.Columns.Add(colTypeCombo);



            // Name column
            DataGridViewTextBoxColumn colName = new DataGridViewTextBoxColumn();
            colName.DataPropertyName = "Name";
            colName.HeaderText = "Name";
            colName.Width = 150;
            this._grid.Columns.Add(colName);

            // set data source
            this._grid.DataSource = this._table;
            this.Controls.Add(this._grid);

        }



        // добавляем 3 человека
        private void FillData()
        {
            DataRow row;
            row = this._table.NewRow();
            row["Type"] = 2;
            row["Name"] = "Вася";
            this._table.Rows.Add(row);

            row = this._table.NewRow();
            // в данном случае тип волос неизвестен
            // row["Type"] = 1;
            row["Name"] = "Петя";
            this._table.Rows.Add(row);

            row = this._table.NewRow();
            row["Type"] = 1;
            row["Name"] = "Коля";
            this._table.Rows.Add(row);

        }

        private void CreateTable()
        {
            this._table = new DataTable();
            // первичный ключ
            DataColumn colId = new DataColumn("ID", typeof(int));
            colId.AutoIncrement = true;
            colId.AutoIncrementSeed = 1;

            // какой-то классификатор ( к примеру тип волос )
            DataColumn colType = new DataColumn("Type", typeof(int));
            colType.AllowDBNull = true;

            // имя человека
            DataColumn colName = new DataColumn("Name", typeof(string));

            _table.Columns.Add(colId);
            _table.Columns.Add(colType);
            _table.Columns.Add(colName);

            DataColumn[] keys = new DataColumn[1];
            keys[0] = colId;
            _table.PrimaryKey = keys;
        }



    }

    // класс для хранения типов чего-либо ( в данном случае типов волос )
    public class TypeItem
    {
        private int _id;
        private string _name;

        public TypeItem(int id, string name)
        {
            this.ID = id;
            this.Name = name;
        }

        public int ID
        {
            get { return this._id; }
            set { this._id = value; }
        }
        public string Name
        {
            get { return this._name; }
            set { this._name = value; }
        }
        public override string ToString()
        {
            return this.ID.ToString() + " - " + this.Name;
        }
    }
}



Заранее благодарен.
Re: DataGridViewComboBoxColumn, будь он неладен
От: baranovda Российская Империя  
Дата: 23.09.08 20:09
Оценка:
Здравствуйте, karapetyan_ashot, Вы писали:

Раз уж используем датасеты, то разумнее всего
1) Справочник "Тип волос" вынести в отдельную таблицу датасета и связать его Relation-ом с таблицей "Людей"
2) К каждой таблице датасета прилепить BindingSource
3) Прицепить DataGridView и его DataGridViewComboBoxColumn, используемую как lookup-editor, каждый к соответствующему BindingSource (см. DataGridViewComboBoxColumn.DataSource, DataGridViewComboBoxColumn.DisplayMember, DataGridViewComboBoxColumn.ValueMember)
Re[2]: DataGridViewComboBoxColumn, будь он неладен
От: karapetyan_ashot  
Дата: 24.09.08 05:12
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Здравствуйте, karapetyan_ashot, Вы писали:


B>Раз уж используем датасеты, то разумнее всего

B>1) Справочник "Тип волос" вынести в отдельную таблицу датасета и связать его Relation-ом с таблицей "Людей"
B>2) К каждой таблице датасета прилепить BindingSource
B>3) Прицепить DataGridView и его DataGridViewComboBoxColumn, используемую как lookup-editor, каждый к соответствующему BindingSource (см. DataGridViewComboBoxColumn.DataSource, DataGridViewComboBoxColumn.DisplayMember, DataGridViewComboBoxColumn.ValueMember)

Я специально отказался от второй таблицы в примере. Ведь если я свяжу список комбобокса со второй таблицей, то комбобокс
будет показывать ТОЛЬКО строки из второй таблицы, а там ведь не будет строки со значением: [null]-[неопределено].
Именно поэтому я решил, что нужно вручную заполнять список комбобокса, и при этом добавить одно знаяение для [null]-[неопределено]
Re: DataGridViewComboBoxColumn, будь он неладен
От: karapetyan_ashot  
Дата: 25.09.08 05:04
Оценка:
Решение нашел!
Пример:


using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Data;

namespace MSComboSample
{
    public class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.Run(new frmTest());
        }
    }
    public class frmTest : Form
    {
        DataGridView _grdTask = new DataGridView();
        DataSet _dataSet;

        public frmTest()
        {
            this.Load += new EventHandler(frmTest_Load);
        }

        void frmTest_Load(object sender, EventArgs e)
        {
            this.Text = "DataGridViewComboBoxColumn test form";
            this.Width = 530;
            this.Height = 260;

            this.CreateDataSet();
            this.FillData();
            this.CreateGrids();
        }

        private void CreateGrids()
        {
            // size, location
            this._grdTask.Size = new Size(500, 210);
            this._grdTask.Location = new Point(10, 10);

            // columns
            this._grdTask.AutoGenerateColumns = false;
            DataGridViewTextBoxColumn colID = new DataGridViewTextBoxColumn();
            colID.HeaderText = "ID";
            colID.DataPropertyName = "ID";
            colID.ReadOnly = true;

            DataGridViewComboBoxColumn colEmpID = new DataGridViewComboBoxColumn();
            colEmpID.Name = "EmpID";
            colEmpID.HeaderText = "Employee ID";
            colEmpID.DataPropertyName = "EmployeeID";
            colEmpID.DisplayMember = "Name";
            colEmpID.ValueMember = "ID";
            // populate items
            // null value
            colEmpID.Items.Add(new ComboItem(DBNull.Value, "not assigned"));
            // employees
            foreach (DataRow row in this._dataSet.Tables["Employee"].Rows)
                colEmpID.Items.Add(new ComboItem(row["ID"], row["Name"].ToString()));

            // check column
            DataGridViewTextBoxColumn colCheck = new DataGridViewTextBoxColumn();
            colCheck.HeaderText = "Check EmpID value";
            colCheck.DataPropertyName = "EmployeeID";
            colCheck.Width = 130;
            colCheck.DefaultCellStyle.NullValue = "<NULL>";

            DataGridViewTextBoxColumn colTask = new DataGridViewTextBoxColumn();
            colTask.HeaderText = "Task";
            colTask.DataPropertyName = "Task";

            this._grdTask.Columns.Add(colID);
            this._grdTask.Columns.Add(colEmpID);
            this._grdTask.Columns.Add(colCheck);
            this._grdTask.Columns.Add(colTask);
            
            // data source
            this._grdTask.DataSource = this._dataSet;
            this._grdTask.DataMember = "Task";

            this.Controls.Add(this._grdTask);

            // for <Ctrl>+<0>
            this._grdTask.KeyDown += new KeyEventHandler(_grdTask_KeyDown);
        }

        // <Ctrl>+<0>
        void _grdTask_KeyDown(object sender, KeyEventArgs e)
        {
            if (this._grdTask.CurrentCell.ColumnIndex == this._grdTask.Columns["EmpID"].Index)
            {
                if (e.Control && (e.KeyCode == Keys.D0 || e.KeyCode == Keys.NumPad0))
                {
                    this._grdTask.CurrentCell.Value = DBNull.Value;
                    e.Handled = true;
                }
            }
        }

        private void FillData()
        {
            DataRow row;
            // employee
            row = this._dataSet.Tables["Employee"].NewRow();
            row["Name"] = "Emp 1";
            this._dataSet.Tables["Employee"].Rows.Add(row);

            row = this._dataSet.Tables["Employee"].NewRow();
            row["Name"] = "Emp 2";
            this._dataSet.Tables["Employee"].Rows.Add(row);

            row = this._dataSet.Tables["Employee"].NewRow();
            row["Name"] = "Emp 3";
            this._dataSet.Tables["Employee"].Rows.Add(row);

            // task
            row = this._dataSet.Tables["Task"].NewRow();
            row["Task"] = "Task 1";
            this._dataSet.Tables["Task"].Rows.Add(row);

            row = this._dataSet.Tables["Task"].NewRow();
            row["EmployeeID"] = 3;
            row["Task"] = "Task 2";
            this._dataSet.Tables["Task"].Rows.Add(row);

            row = this._dataSet.Tables["Task"].NewRow();
            row["Task"] = "Task 3";
            this._dataSet.Tables["Task"].Rows.Add(row);

        }

        private void CreateDataSet()
        {
            this._dataSet = new DataSet();
            // employees
            DataTable tEmployee = new DataTable("Employee");
            // id
            DataColumn colEmpID = new DataColumn("ID", typeof(int));
            colEmpID.AutoIncrement = true;
            colEmpID.AutoIncrementSeed = 1;
            colEmpID.Unique = true;
            colEmpID.AllowDBNull = false;
            // name
            DataColumn colEmpName = new DataColumn("Name", typeof(string));

            tEmployee.Columns.Add(colEmpID);
            tEmployee.Columns.Add(colEmpName);
            tEmployee.PrimaryKey = new DataColumn[] { colEmpID };

            // tasks
            DataTable tTask = new DataTable("Task");
            // id
            DataColumn colTaskID = new DataColumn("ID", typeof(int));
            colTaskID.AutoIncrement = true;
            colTaskID.AutoIncrementSeed = 1;
            colTaskID.Unique = true;
            colTaskID.AllowDBNull = false;
            // employee id
            DataColumn colTaskEmpID = new DataColumn("EmployeeID", typeof(int));
            colTaskEmpID.AllowDBNull = true;
            colTaskEmpID.DefaultValue = DBNull.Value;
            // task name
            DataColumn colTaskName = new DataColumn("Task", typeof(string));

            tTask.Columns.Add(colTaskID);
            tTask.Columns.Add(colTaskEmpID);
            tTask.Columns.Add(colTaskName);
            tTask.PrimaryKey = new DataColumn[] { colTaskID };

            this._dataSet.Tables.Add(tEmployee);
            this._dataSet.Tables.Add(tTask);

            DataRelation rel = new DataRelation("TaskEmployee", colEmpID, colTaskEmpID);


        }
    }

    public class ComboItem
    {
        private object _id;
        private string _name;
        
        public ComboItem(object id, string name)
        {
            this._id = id;
            this._name = name;
        }

        public object ID
        {
            get { return this._id; }
            set { this._id = value; }
        }
        public string Name
        {
            get { return this._name; }
            set { this._name = value; }
        }
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.