# برنامه نویسی با محصولات مایکروسافت > برنامه نویسی مبتنی بر Microsoft .Net Framework > C#‎‎ > حرفه ای: مطالبی در مورد DataGridView

## amiramt

با سلام

 در این تاپیک قصد داریم مطالب کمیاب و مفید و کاربردی در مورد دیتا گرید ویو را برایتان ارسال کنیم .

*از تمام صفحات این تاپیک دیدن نمایید شاید مطلب مورد نظر شما در صفحات دیگر باشد .* 

شما می توانید این مطالب را در وبلاگم مشاهده نمایید .
wWw.Dgv.Blogfa.Com

----------


## amiramt

چیزی که من از آرگومان e در رویدادها فهمیدم اینکه  e آرگومانی است که می تواند حاوی اطلاعاتی در مورد آن رویداد باشد . مثلا در  رویداد کلیک می توان با کمک این آرگومان متوجه شد که کدام دکمه موس فشرده  شده است  و در Datagrid معرف سلولی است که بروی آن کلیک شده یا در حال ویرایش است و یا به آن سلول وارد شده ایم .مثلا



private void dataGridView1_CellMouseDown( object sender , DataGridViewCellMouseEventArgs e )
        {
            if ( e.Button == MouseButtons.Left ) 
            {
                   //----   اگر دکمه چپ ماوس روی دیتا گرید فشرده شد
            }
            if ( e.ColumnIndex == 1 )
            { 
                //---- ( اگر ستونی که ماوس روی آن فشرده شده است ستون با اندیس 1 است.( یعنی ستون دوم در دیتاگرید   
            
            }
            if ( e.RowIndex == 2 )
            {
                //---- ( اگر سطری که ماوس روی آن فشرده شده است سطر با اندیس 2 است.( یعنی روی سطر دوم در دیتاگرید کلیک شده   
            }

        }









private void dataGridView1_KeyPress( object sender , KeyPressEventArgs e )
        {
            if ( e.KeyChar == 'م' )
            { 
                //---   اگر حرف 'م' فشرده شده است            
            }
        }









private void dataGridView1_KeyDown( object sender , KeyEventArgs e )
        {
            if ( e.KeyCode == Keys.Escape )
            {
                //----        فشرده شده است Esc اگر کلید فشرده 
            
            }

            if ( e.KeyCode == Keys.Up )
            {
                //----         اگر کلید اروکی بالا فشرده شده شده است
            }
        }




توجه کنید که رویداد keypress   و keyDown  در TextBox هم شبیه به همین است .

----------


## amiramt

انتخاب 20 آیتم آخر از دیتابیس


select top(20) name , family from tbl_Student order by mycode desc 



برای اینکه همیشه رکوزد آخر برای فعال باشد در رویداد مناسب کد زیر را بنویسید

Dgv.CurrentCell = Dgv.Rows[ Dgv.RowCount - 1 ].Cells[ 0 ];    // فعال  کردن رکورد آخر

----------


## amiramt

با استفاده از این دیتاگرید که به صورت یه Component می باشد می توانید کارهای زیاد و عجیبی که دیتاگرید معمولی این قابلیت ها را ندارد را انجام دهید چند نمونه کار هایی که می توانید انجام دهید :







برای آموزش و طریقه ی کار با این دیتاگرید به ادرس زیر بروید

http://www.rustemsoft.com/dgvcolumns.asp#


فایل این دیتاگرید را می توایند از لینک زیر دانلود کنید .

http://www.rustemsoft.com/DataGridViewColumnsTrial.zip

----------


## amiramt

این هم ابزاری که MaskTextBox رو به DataGridView اضافه می کنه.
تنها کاری که باید بکنین اینه:
1. روی  Project، کلیک راست کنین 
    add reference2. 
 3. دکمه Add رو بزنین.
4. به تب Browse برین.
5. فایل Attach شده رو انتخاب کنین و دکمه Ok رو فشار بدین.
6. به فرمتون برین و یه DataGridView بکشین.
7. حالا از Properties ها DataGridView، گزینه Columns رو انتخاب کنین.
8. توی لیست Type، یه گزینه اضافه شده به نام DataGridViewMaskedTextColumn و این همون چیزیه که شما می خواین  و در همین جا با استفاده از خاصیت Mask  می توانید قالب خود را مشخص کنید مثلا 
###,##,##

----------


## sa_ghaznavi

اگه می خواهید با زدن اینتر به جای رفتن به سطر بعدی به ستون بعدی برید کد زیر مشکلتون رو حل می کنه :

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            const int WM_KEYDOWN = 0x100;
            const int WM_SYSKEYDOWN = 0x104;
            if ((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
            {
                switch (keyData)
                {
                    case Keys.Enter:
                        try
                        {
                            grid1.CurrentCell = grid1[grid1.CurrentCell.ColumnIndex + 1, grid1.CurrentCell.RowIndex];
                        }
                        catch { }
                        return true;
                    case Keys.Right:
                        try
                        {
                            grid1.CurrentCell = grid1[grid1.CurrentCell.ColumnIndex - 1, grid1.CurrentCell.RowIndex];
                        }
                        catch { }
                        return true;
                    case Keys.Left:
                        try
                        {
                            grid1.CurrentCell = grid1[grid1.CurrentCell.ColumnIndex + 1, grid1.CurrentCell.RowIndex];
                        }
                        catch { }
                        return true;
                    case Keys.Up:
                        try
                        {
                            grid1.CurrentCell = grid1[grid1.CurrentCell.ColumnIndex, grid1.CurrentCell.RowIndex - 1];
                        }
                        catch { }
                        return true;
                    case Keys.Down:
                        try
                        {
                            grid1.CurrentCell = grid1[grid1.CurrentCell.ColumnIndex, grid1.CurrentCell.RowIndex + 1];
                        }
                        catch { }
                        return true;
                }
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

----------


## mehdis2

سلام اين بگيريد بد نيست :خجالت: 
http://www.windowsclient.net/Samples...View%20FAQ.doc

----------


## niloo17

سلام دوستان 
با این کد می تونین کلید اینتر را در یک سلول کنترل کنید 

public class MyDataGridView : DataGridView
    {
        private protectedoverridebool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Enter)
            {
                DataGridViewCell cell = CurrentCell;
                base.ProcessDialogKey(keyData);
                CurrentCell = Rows[cell.RowIndex].Cells[cell.ColumnIndex + 1];
                returntrue;
            }
            returnbase.ProcessDialogKey(keyData);
        }
    }

----------


## amireto

با سلام خدمت همه دوستان
این کد برای افزودن یک یا چند ردیف جدید به هر جای گرید که بخواهید (ابتدا انها رکورد فعلی)
البته گریدی که بایند نباشه
امیدوارم که مفید باشد

       private void AddRows(params DataGridViewRow[] rows)
        {
            InsertRows(dataGridView1.CurrentRow.Index , rows);
        }//جایی که باید رکورد اضافه شود

        // Workaround for bug that prevents DataGridViewRowCollection.InsertRange
        // from working when any rows before the insertion index are selected.
        private void InsertRows(int index, params DataGridViewRow[] rows)
        {
            System.Collections.Generic.List<int> selectedIndexes =
                new System.Collections.Generic.List<int>();
            foreach (DataGridViewRow row in dataGridView1.SelectedRows)
            {
                if (row.Index >= index)
                {
                    selectedIndexes.Add(row.Index);
                    row.Selected = false;
                }
            }
            dataGridView1.Rows.InsertRange(index, rows);
            foreach (int selectedIndex in selectedIndexes)
            {
                dataGridView1.Rows[selectedIndex].Selected = true;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            DataGridViewRow row = new DataGridViewRow();
            AddRows(row);
        }

و خلاصه کد افزودن یک رکورد در جای دلخواه


        private void button1_Click(object sender, EventArgs e)
        {
            DataGridViewRow row = new DataGridViewRow();
            dataGridView1.Rows.InsertRange(dataGridView1.CurrentRow.Index, row);
        }

----------


## kiumarsknb

سلام
سوالات متداول از DataGridView

----------


## amiramt

سلام
امروز خودم می خواستم به صورت برنامه نویسی دیتا گریدم را بر حسب یک ستون مرتب کنم ، هرچی به کدها دسته و پنجره نرم کردم نشد ، از دستور Sort هم استفاده کردم ، ولی نمی دونم چه جوری ازش استفاده کنم 
در هر صورت موفق شدم این کار را با کمک نت انجام بدم.
گفتم این یک خط کد را برا شما هم بذارم ، شاید به کارتون بیاد .

Dgv1.Sort(Dgv1.Columns["mycode"], ListSortDirection.Ascending);

----------


## akobar

من یک گرید دارم و میخوام وقتی ctrl+f زدم اگه یک ستون انتخاب شده باشد یک فرم ظاهر شود و کاربر در تکست باکس روی فرم مقدار را وارد کند و با زدن دکمه جستجو سلولی که این مقدار را دارد را انتخاب کند
اگه لطف کنید برنامه را ببینید ممنون میشم
خیلی خیلی بهش احتیاج دارم

----------


## shahab_ss

با فرض اینکه شما در یک فرم این کنترل ها رو داشته باشید :

DatagridView dgvUser;
TextBox txt_Search;




int _Column = 0;
int _Row = 0;
private void SearchGrid()
        {
            dgvUser.deSelectGrid(dgvUser);

            //maxSearches = the # of cells in the grid
            int maxSearches = dgvUser.Rows.Count * dgvUser.Columns.Count + 1;
            int idx = 1;
            bool isFound = false;
            string searchValue = txt_Search.Text.ToUpper();

            if (Convert.ToBoolean(txt_Search.Text.Length))  
            {
                // If the item is not found and you haven't looked at every cell, keep searching
                while ((!isFound) & (idx < maxSearches))
                {
                    // Only search visible cells
                    if (dgvUser.Columns[_Column].Visible)
                    {
                        // Do all comparing in UpperCase so it is case insensitive
                        if (dgvUser[_Column, _Row].Value != null && dgvUser[_Column, _Row].FormattedValue.ToString().ToUpper().Contains(sear  chValue))
                        {
                            // If found position on the item
                            //dgvUser.FirstDisplayedScrollingRowIndex = _Row;
                            //dgvUser[_Column, _Row].Selected = true;
                            BindingManagerBase bmb = this.BindingContext[dgvUser.DataSource, dgvUser.DataMember];
                            bmb.Position = _Row;

                            isFound = true;
                            txtStatus.ResetText();

                        }
                    }

                    // Increment the column.
                    _Column++;

                    // If it exceeds the column count
                    if (_Column == dgvUser.Columns.Count)
                    {
                        _Column = 0; //Go to 0 column
                        _Row++;      //Go to the next row

                        // If it exceeds the row count
                        if (_Row == dgvUser.Rows.Count)
                        {
                            _Row = 0; //Start over at the top
                        }
                    }

                    idx++;
                }

                // If isFound = false then the phrase has not been found in the grid
                if (!isFound)
                {
                    txtStatus.Text = "Item Not Found";
                }
            }
        }

----------


## amiramt

> سلام منظور من از متفاوت بودن ، متفاوت بودن نوع داده ايي ستون نيست
> من ميخام ببينم چطوري ميشه براي هر سطر در ستون كومبو باكس دوم مقادير متفاوتي داشت كه اين مقادير رو از ديتابيس توش لود ميكنيم؟؟


منم همین کار را تو پروژه ام انجام دادم ، به صورت زیر عمل کنید :


        private void Dgv_Main_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == Dgv_Main.Columns["Col_Article_Name"].Index)
            {
                Cls_Main.Cls_Articles put = new Cls_Main.Cls_Articles();
                DataGridViewComboBoxCell Cell_Unit1 = new DataGridViewComboBoxCell();
                put.Put_Unit_Article_To_Dgv_Cell(Convert.ToString(  Dgv_Main["Col_Article_Name", e.RowIndex].Value), ref Cell_Unit1);
                ((DataGridViewComboBoxCell)Dgv_Main.Rows[e.RowIndex].Cells["col_unit_article"]).DataSource = Cell_Unit1.Items;
            }

        }




public void Put_Unit_Article_To_Dgv_Cell(String _Article_Name, ref DataGridViewComboBoxCell Cell_Unit)
        {
            source(" select  unit  from tbl_articles where name ='" + _Article_Name + "'");
            Cell_Unit.Items.Clear();
            for (int i = 0; i < ds.Tables["t1"].Rows.Count; i++)
            {
                Cell_Unit.Items.Add(ds.Tables["t1"].Rows[i]["unit"].ToString());

            }
        }

----------


## amireto

سلام دوست عزيز
من هم مدتي پيش چنين مشكلي داشتم و مطرح كردم كسي جواب نداد بالاخره با سعي و تلاش و جمع اوري مطالب پراكنده اين سايت اين مشكل را يه جوري حل كردم



> .اما مشتري در عين حال دلش مي خواد وقتي كه اينتر و مي زنه فوكوس به سلول سمت چپي بره در همان رديف (چون فرم فارسي هست و رايت تو لفت)،


براي حل اين مشكل مطالب فراوونه اما من يك كلاس تو پروژم درست كردم كه اون كلاس از ديتاگريد خود ويژوال يا هر ديتاگريدي از كامپوننت هاي مختلف ارث ميبره و خواص و متدهاي مورد نظرم رو بهش افزودم

        bool enterIsTab = true;
        public bool EnterIsTab
        {
            get
            {
                return enterIsTab;
            }
            set
            {
                enterIsTab = value;
            }
        }


        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
        {
            if (msg.WParam.ToInt32() == (int)Keys.Enter)
            {
                if (enterIsTab)
                {
                    SendKeys.Send("{tab}");
                    return true;
                }            
                
            }

            return base.ProcessCmdKey(ref msg, keyData);
        }





> و وقتي مثلا به سلول چهارم ميرسه و اينتر رو مي زنه فوكوس به سلول پنجم نبايد بره ، بلكه بايد رديف جاري رو ترك كنه و بره به رديف بعدي در ضمن يادمون نره كه بايد به ستون دوم رديف بعدي بره چون ستون اول رديف هست و تنها كارش اينكه يه شماره رديف بندازه(read only هستش) .


براي حل اين مشكل اگر از روش من استفاده كني  بايد در رويداد _CellEnter  ديتاگريد روي فرمت 
خواصيت enterIsTab ديتاگريد رو false و پس از خروج دوباره true كني

 if (e.ColumnIndex == 4)
            {
                grdDatagrid.EnterIsTab = false;
            }


حال در رويداد  _KeyDown مربوط به ديتاگريد چنين كدي بايد بنويسي

if (e.KeyCode == Keys.Enter)
            {
 if (grdDatagrid.CurrentCell.ColumnIndex == 4)
                {
                    grdDatagrid.Rows.Add();
                    grdDatagrid.CurrentCell = grdDatagrid[1, grdDatagrid.RowCount - 1];
                    grdDatagrid.BeginEdit(true);
                
                }
{

عدد 1 يعني دومين ستون حال مي تونه هر ستوني باشه
اميدوارم مشكل با اين توضيحات حل بشه  :لبخند:

----------


## Esmail Solhkhah

> سلام 
> با تشکر از اطلاعات کاملتون من تمام پست ها رو خوندم. من نیاز دارم یک شماره ردیف در DataGridView داشته باشم. که هنگامب که سطری حذف میشه یا سطری جدید اضافه می شه باز هم شماره ردیف درست نمایش داده بشه.
> چطور میتونم این کار رو انجام بذم
> با تشکــــــــر



  private void dataGridViewX1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            using (SolidBrush b = new SolidBrush(Color.Black))
            {
                e.Graphics.DrawString((e.RowIndex).ToString(),
                e.InheritedRowStyle.Font, b,
                (sender as DataGridView).Width - e.RowBounds.Location.X - 5,
                e.RowBounds.Location.Y + 4);
            }
        }

----------


## Esmail Solhkhah

*با استفاده از این متد و کلاس کمکی اون میتونید از دیتاگریدویو یه دیتاتیبل بگیرید (هرجوری که دیتاگرید داره اطلاعات نشون میده به همون صورت براتون یه دیتاتیبل برمیگردونه)*

        public static DataTable GetDataGridViewDataSource(DataGridView dgv)
        {
            DataTable dt = new DataTable("dt");

            try
            {
                List<DataGridViewRowInfo> MyColumns = new List<DataGridViewRowInfo>();
                foreach (DataGridViewColumn dgvC in dgv.Columns)
                {
                    if (dgvC.Visible != false && dgvC.Name.ToLower() != "grd_id")
                    {
                        DataGridViewRowInfo info = new DataGridViewRowInfo(dgvC.Name, dgvC.HeaderText);
                        MyColumns.Add(info);
                    }
                }
                foreach (DataGridViewRowInfo info in MyColumns)
                {
                    DataColumn dc = new DataColumn(info.HeaderText);
                    dt.Columns.Add(dc);
                }
                for (int i = 0; i != dgv.Rows.Count; i++)
                {
                    DataRow dr = dt.NewRow();
                    foreach (DataGridViewRowInfo info in MyColumns)
                    {
                        dr[info.HeaderText] = dgv.Rows[i].Cells[info.Name].EditedFormattedValue.ToString();
                    }
                    dt.Rows.Add(dr);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            return dt;
        }



 public class DataGridViewRowInfo
    {
        string _Name;
        string _HeaderText;

        public DataGridViewRowInfo()
        {
        }

        public DataGridViewRowInfo(string name, string headerText)
        {
            _Name = name;
            _HeaderText = headerText;
        }

        public string Name { get { return _Name; } set { _Name = value; } }
        public string HeaderText { get { return _HeaderText; } set { _HeaderText = value; } }

        public override string ToString()
        {
            return _HeaderText;
        }
    }

----------


## Esmail Solhkhah

فرض کنیم دوتا جدول دارم اولی جدول *واحدها* شامل کد واحد و نام واحد

دومی جدول *کالا* شامل کد کالا - کد واحد - نام کالا

حالا اگه بخایم گردیدویو رو به جدول کالا بایند کنیم طبیعتا تو گرد فیلدهای کد کالا- کد واحد و نام کالا دیده خواهند شد. حالا اگه بخایم بجای کد واحد ، نام واحد تو گرید بیاد:

اول رو گرید راست کلیک کرده بعد Edit Columns

بعد فیلد کد واحد رو از لیست Column های گرید انتخاب میکنیم بعد از سمت راست Column Type اونو باز 

میکنیم و قرارش میدیم DayaGridViewComboBoxColumn 

بعد از اینکه Column Type رو تغییر دادیم چهار تا آیتم به این لیست اضافه میشه

شامل Items - DataSource - DisplayMember - ValueMember 

1.JPG

حالا میتونیم این کامبوباکس رو به تیبل واحد بایند کنیم و DisplayMember اونو بذاریم Name از جدول واحد

و ValueMember اونو بذاریم Code از جدول واحد.

در اینصورت بجای کد واحد نام واحد تو گرید دیده میشه

فقط میمونه یه نکته کوچیک اونم اینکه این ستون داخل گرید بصورت یه کامبو دیده میشه

2.JPG

فقط کافیه خاصیت DisplayStyle  مربوط به اون ستون رو به Nothing ست کنیم.

----------


## Esmail Solhkhah

*DataGridView CellBlink*

----------


## Esmail Solhkhah

*
یه فایل Pdf خوب جهت بررسی امکانات و برنامه نویسی DataGridView*

http://ifile.it/93ghw6n

----------


## Esmail Solhkhah

*مثالهای کاربردی در زمینه کار با دیتاگریدویو*

http://www.dotnetspider.com/resources/Category532.aspx

----------


## رافعی مهدی

فقط عدد در سلول دیتاگرید ویو، تنها کافی است یک delegate برای این کار بسازیم:

        private KeyPressEventHandler editingControlKeyPressedHandler = delegate(object sender, KeyPressEventArgs e)
        {
            if (!char.IsNumber(e.KeyChar) && !char.IsControl(e.KeyChar))
                e.Handled = true;
        };

        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            TextBox editingTextBox = e.Control as TextBox;

            if (dataGridView1.CurrentCell.ColumnIndex == dataGridView1.Columns["colCount"].Index)
            {
                if (editingTextBox != null)
                    editingTextBox.KeyPress += editingControlKeyPressedHandler;
            }
            else 
                if (editingTextBox != null)
                    editingTextBox.KeyPress -= editingControlKeyPressedHandler;
        }

----------


## SajjadStr

سلام ذخیره اطلاعات دیتا گرید لود مجدد به همان شکلی که بوده چطوریه؟

----------

