sticky
FAQ - Windows Forms Data Controls

Все ответы

  • 1.    Как я могу запретить пользователю устанавливать фокус в определенной ячейке?

     По умолчанию модель навигации DataGridView не предусматривает такую возможность. Вы можете реализовать свою логику навигации, переопределив соответствующие методы клавиатуры и мыши, такие как DataGridView.OnKeyDown, DataGridView.ProcessDataGridViewKey, DataGridView.SetCurrentCellAddressCore, DataGridView.SetSelectedCellCore, DataGridView.OnMouseDown.

    Например, вы хотите не дать пользователю возможность устанавливать фокус во втором столбце. Для этого вам придется создать потомок DataGridView и переопределить SetCurrentCellAddressCore и SetSelectedCellCore соответствующим образом.

    Пример кода:

      public partial class Form1 : Form
      {
       public Form1()
       {
        InitializeComponent();
       }
     
       private void Form1_Load(object sender, EventArgs e)
       {
        DataTable dt = new DataTable();
        dt.Columns.Add("c1");
        dt.Columns.Add("c2");
        dt.Columns.Add("c3");
        for (int j = 0; j < 10; j++)
        {
         dt.Rows.Add("aaa" + j.ToString(), "bbb");
        }
     
        this.myDataGridView1.DataSource = dt;
        this.myDataGridView1.ColumnToSkip = 1;
       }
      }
     
      public class myDataGridView : DataGridView
      {
       private int columnToSkip = -1;
     
       public int ColumnToSkip
       {
        get { return columnToSkip; }
        set { columnToSkip = value; }
       }
     
       protected override bool SetCurrentCellAddressCore(int columnIndex, int rowIndex,
        bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick)
       {
        if (columnIndex == this.columnToSkip && this.columnToSkip != -1)
        {
         if (this.columnToSkip == this.ColumnCount - 1)
         {
          return base.SetCurrentCellAddressCore(0, rowIndex + 1,
           setAnchorCellAddress, validateCurrentCell, throughMouseClick);
         }
         else
         {
          if (this.ColumnCount != 0)
          {
           return base.SetCurrentCellAddressCore(columnIndex + 1, rowIndex,
            setAnchorCellAddress, validateCurrentCell, throughMouseClick);
          }
         }
        }
        return base.SetCurrentCellAddressCore(columnIndex, rowIndex,
         setAnchorCellAddress, validateCurrentCell, throughMouseClick);
       }
     
       protected override void SetSelectedCellCore(int columnIndex, int rowIndex, bool selected)
       {
        if (columnIndex == this.columnToSkip)
        {
         if (this.columnToSkip == this.ColumnCount - 1)
         {
          base.SetSelectedCellCore(0, rowIndex + 1, selected);
         }
         else
         {
          if (this.ColumnCount != 0)
          {
           base.SetSelectedCellCore(columnIndex + 1, rowIndex, selected);
          }
         }
        }
        else
        {
         base.SetSelectedCellCore(columnIndex, rowIndex, selected);
        }
       }
      }
    

     


    Для связи [mail]
    29 апреля 2011 г. 8:31
  • 2.    Как можно вывести вертикальный текст в ячейке?

    Для того чтобы вывести в ячейке текст вертикально, вы должны обработать событие CellPainting и в нем с помощью флага StringFormatFlags.DirectionVertical самостоятельно рисовать текст в ячейке. Пример ниже демонстрирует, как это делается:

        private void Form1_Load(object sender, EventArgs e)
        {
          DataTable dt = new DataTable();
          dt.Columns.Add("c1");
          dt.Columns.Add("c2");
          for (int j = 0; j < 10; j++)
          {
            dt.Rows.Add("aaaaaaaaa", "bbbb");
          }
          this.dataGridView1.DataSource = dt;
     
          for (int j = 0; j < 10; j++)
          {
            int height = TextRenderer.MeasureText(
              this.dataGridView1[0, j].Value.ToString(),
              this.dataGridView1.DefaultCellStyle.Font).Width;
            this.dataGridView1.Rows[j].Height = height;
          }
     
          this.dataGridView1.CellPainting += new
             DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting); ;
        }
     
        void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
          if (e.ColumnIndex == 0 && e.RowIndex > -1 && e.Value != null)
          {
            e.Paint(e.CellBounds, DataGridViewPaintParts.All
               & ~DataGridViewPaintParts.ContentForeground);
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            sf.FormatFlags = StringFormatFlags.DirectionVertical;
            e.Graphics.DrawString(e.Value.ToString(), e.CellStyle.Font,
              new SolidBrush(e.CellStyle.ForeColor), e.CellBounds, sf);
            e.Handled = true;
          }
        }
    

     


    Для связи [mail]
    29 апреля 2011 г. 8:36
  • 3.    Как изменить тип сортировки по умолчанию (SortMode)?

    По умолчанию установлена автоматическая сортировка (SortMode = DataGridViewColumnSortMode.Automatic), но вам может потребоваться изменить настройку сортировки, для этого вы можете либо пройтись в цикле по всем столбцам и изменить парамерты сортировки, либо переопределить событие добавления нового столбца в нем изменять свойство сортировки:

        public class mydgv : DataGridView
        {
          protected override void OnColumnAdded(DataGridViewColumnEventArgs e)
          {
            base.OnColumnAdded(e);
            e.Column.SortMode = DataGridViewColumnSortMode.NotSortable;
          }
        }
    

     


    Для связи [mail]
    29 апреля 2011 г. 8:37
  • 4.    Как динамически изменить тип ячейки DataGridViewCell?

    Например, может потребоваться во время работы программы изменить тип ячейки с DataGridViewComboBoxCell на DataGridViewTextBoxCell динамически, основываясь на каком-либо значении. Пример того, как это можно сделать:

        private void Form1_Load(object sender, EventArgs e)
        {
          DataTable dt = new DataTable("b");
          dt.Columns.Add("col");
          dt.Rows.Add("bb1");
          dt.Rows.Add("bb2");
          dt.Rows.Add("bb3");
     
          this.dataGridView1.DataSource = dt;
     
          DataGridViewComboBoxColumn cmb = new DataGridViewComboBoxColumn();
          cmb.Items.Add("111");
          cmb.Items.Add("222");
          cmb.Items.Add("333");
          this.dataGridView1.Columns.Add(cmb);
        }
        private void button1_Click(object sender, EventArgs e)
        {
          DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell();
          cell.Value = "bb1";
          this.dataGridView1[1, 1] = cell;
        }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 8:38
  • 5.    Как сделать отображение DataGridViewComboBoxColumn как текстового поля, когда ячейка не в состоянии редактирования?

    Этого можно достичь, установив свойство DataGridViewComboBoxColumn.DisplayStyle в значение DataGridViewComboBoxDisplayStyle.Nothing.

     


    Для связи [mail]
    29 апреля 2011 г. 8:42
  • 6.    Как сделать сложный многоуровневый заголовок столбцов?

    Пример сложного заголовка:

    ________________________________________________

                    |   January       |   February      |     March       |
                    |  Win  | Loss   |  Win   | Loss   |  Win | Loss    |
    ------------------------------------------------------------------
    Team1       |         |          |         |           |          |          |
    Team2       |         |          |         |           |          |          |
    TeamN       |         |          |         |           |          |          |
    ------------------------------------------------------------------

    Чтобы достичь такого эффекта нужно обработать события DataGridView.Painting и DataGridView.CellPainting для того, чтобы нарисовать такой стиль заголовка, какой вы хотите. Ниже пример показывает как это делается:

      private void DgvColumnHeaderMerge_Load(object sender, EventArgs e)
      {
       this.dataGridView1.Columns.Add("JanWin", "Win");
       this.dataGridView1.Columns.Add("JanLoss", "Loss");
       this.dataGridView1.Columns.Add("FebWin", "Win");
       this.dataGridView1.Columns.Add("FebLoss", "Loss");
       this.dataGridView1.Columns.Add("MarWin", "Win");
       this.dataGridView1.Columns.Add("MarLoss", "Loss");
     
       for (int j = 0; j < this.dataGridView1.ColumnCount; j++)
       {
        this.dataGridView1.Columns[j].Width = 45;
       }
       this.dataGridView1.ColumnHeadersHeightSizeMode =
         DataGridViewColumnHeadersHeightSizeMode.EnableResizing;
       this.dataGridView1.ColumnHeadersHeight =
          this.dataGridView1.ColumnHeadersHeight * 2;
       this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment =
         DataGridViewContentAlignment.BottomCenter;
       this.dataGridView1.CellPainting += new
         DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting);
       this.dataGridView1.Paint += new PaintEventHandler(dataGridView1_Paint);
     
      }
     
      void dataGridView1_Paint(object sender, PaintEventArgs e)
      {
       string[] monthes = { "January", "February", "March" };
       for (int j = 0; j < 6; )
       {
        //get the column header cell
        Rectangle r1 = this.dataGridView1.GetCellDisplayRectangle(j, -1, true);
     
        r1.X += 1;
        r1.Y += 1;
        r1.Width = r1.Width * 2 - 2;
        r1.Height = r1.Height / 2 - 2;
        e.Graphics.FillRectangle(new
         SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);
        StringFormat format = new StringFormat();
        format.Alignment = StringAlignment.Center;
        format.LineAlignment = StringAlignment.Center;
        e.Graphics.DrawString(monthes[j / 2],
         this.dataGridView1.ColumnHeadersDefaultCellStyle.Font,
         new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor),
         r1,
         format);
        j += 2;
       }
      }
     
      void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
      {
       if (e.RowIndex == -1 && e.ColumnIndex > -1)
       {
        e.PaintBackground(e.CellBounds, false);
     
        Rectangle r2 = e.CellBounds;
        r2.Y += e.CellBounds.Height / 2;
        r2.Height = e.CellBounds.Height / 2;
        e.PaintContent(r2);
        e.Handled = true;
       }
      }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 8:44
  • 7.    Как создать несколько элементов управления в одной ячейке?

    Создать несколько элементов управления в одной ячейке можно следующим путем:

    1. Создать UserControl, в котором разместить все необходимые элементы управления (например TextBox и Button)
    2. Добавить этот UserControl в коллекцию элементов управления (Controls) DataGridView, при этом изначально сделать UserControl невидимым
    3. Обработать событие CellBeginEdit для того, чтобы отобразить UserControl в текущей ячейке.
    4. Обработать событие CellEndEdit для того, чтобы изменить значение ячейки в соответствии со значением, полученным от UserControl.

    В качестве полного примера можно посмотреть следующие топики:

     


    Для связи [mail]
    29 апреля 2011 г. 8:49
  • 8.    Как отобразить сгруппированные данные в DataGridView?

    Например, вы хотите отобразить данные так:

    Ключевым моментом является обработка события CellPainting для произвольной отрисовки ячейки так, как вы хотите. Ниже приведен пример:

    public class GroupByGrid : DataGridView
        {
     
          protected override void OnCellFormatting(
            DataGridViewCellFormattingEventArgs args)
          {
            // Call home to base
            base.OnCellFormatting(args);
     
            // First row always displays
            if (args.RowIndex == 0)
              return;
     
     
            if (IsRepeatedCellValue(args.RowIndex, args.ColumnIndex))
            {
              args.Value = string.Empty;
              args.FormattingApplied = true;
            }
          }
     
          private bool IsRepeatedCellValue(int rowIndex, int colIndex)
          {
            DataGridViewCell currCell =
              Rows[rowIndex].Cells[colIndex];
            DataGridViewCell prevCell =
              Rows[rowIndex - 1].Cells[colIndex];
     
            if ((currCell.Value == prevCell.Value) ||
              (currCell.Value != null && prevCell.Value != null &&
              currCell.Value.ToString() == prevCell.Value.ToString()))
            {
              return true;
            }
            else
            {
              return false;
            }
          }
     
          protected override void OnCellPainting(
            DataGridViewCellPaintingEventArgs args)
          {
            base.OnCellPainting(args);
     
            args.AdvancedBorderStyle.Bottom =
              DataGridViewAdvancedCellBorderStyle.None;
     
            // Ignore column and row headers and first row
            if (args.RowIndex < 1 || args.ColumnIndex < 0)
              return;
     
            if (IsRepeatedCellValue(args.RowIndex, args.ColumnIndex))
            {
              args.AdvancedBorderStyle.Top =
                DataGridViewAdvancedCellBorderStyle.None;
            }
            else
            {
              args.AdvancedBorderStyle.Top = AdvancedCellBorderStyle.Top;
            }
          }
        }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 8:52
  • 9.    Как сделать так, чтобы кнопка Enter делала то же самое, что и кнопка Tab?

    Для того, чтобы сделать так чтобы Enter работал как Tab вы должны создать своего наследника DataGridView и в нем обработать 2 случая. Один из них – когда DataGridView не находится в режиме редактирования: в этом случае вы переопределяете метод ProcessDataGridViewKey для того чтобы изменить логику навигации как хотите. Другой случай – когда DataGridView в режиме редактирования: в этом случае Enter обрабатывается в методе ProcessDialogKey и вы должны переопределить его, добавив свою логику. Ниже пример демонстрирует, как это делается:

     public class MyDataGridView : DataGridView
      {
        protected override bool ProcessDataGridViewKey(KeyEventArgs e)
        {
          if (e.KeyCode == Keys.Enter)
          {
            this.ProcessTabKey(e.KeyData);
            return true;
          }
          return base.ProcessDataGridViewKey(e);
        }
    
        protected override bool ProcessDialogKey(Keys keyData)
        {
          if (keyData == Keys.Enter)
          {
            this.ProcessTabKey(keyData);
            return true;
          }
          return base.ProcessDialogKey(keyData);
        }
      }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 8:54
  • 10.    Как ограничить ввод только цифрами в текстовом столбце?

    Когда текстовая ячейка переходит в режим редактирования, то вызывается событие EditingControlShowing, на которое необходимо подписаться для дальнейшего ограничения ввода. В этом событие мы получаем текстовое поле, в которое осуществляется ввод. И подписавшись на события нажатия клавиш, этот ввод можно ограничить. Ниже пример демонстрирует, как это делается:

        public partial class DgvNumberOnlyColumn : Form
        {
          public DgvNumberOnlyColumn()
          {
            InitializeComponent();
          }
     
          private void DgvNumberOnlyColumn_Load(object sender, EventArgs e)
          {
            this.dataGridView1.Columns.Add("col1", "col1");
            this.dataGridView1.Columns.Add("col2", "col2");
            this.dataGridView1.Rows.Add();
            this.dataGridView1.EditingControlShowing += new
               DataGridViewEditingControlShowingEventHandler(
               dataGridView1_EditingControlShowing);
          }
     
          void dataGridView1_EditingControlShowing(object sender,
             DataGridViewEditingControlShowingEventArgs e)
          {
            if (this.dataGridView1.CurrentCell.ColumnIndex == 0)
            {
              if (e.Control is TextBox)
              {
                TextBox tb = e.Control as TextBox;
                tb.KeyPress -= new KeyPressEventHandler(tb_KeyPress);
                tb.KeyPress += new KeyPressEventHandler(tb_KeyPress);
              }
            }
          }
     
          void tb_KeyPress(object sender, KeyPressEventArgs e)
          {
            if (!(char.IsDigit(e.KeyChar)))
            {
              Keys key = (Keys)e.KeyChar;
     
              if (!(key == Keys.Back || key == Keys.Delete))
              {
                e.Handled = true;
              }
            }
          }
        }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 8:55
  • 11.    Как сделать отображение табуляции (\t) в DataGridViewCell?

    Когда DataGridView отображает значение ячейки, то табуляция \t  игнорируется по умолчанию. Чтобы сделать рабочим \t необходимо подписаться на событие CellPainting и отрисовать текст самостоятельно:

      void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
      {
       e.Paint(e.CellBounds,
        DataGridViewPaintParts.All & ~DataGridViewPaintParts.ContentForeground);
       if (e.Value != null)
       {
        e.Graphics.DrawString(e.Value.ToString(),
         e.CellStyle.Font,
         new SolidBrush(e.CellStyle.ForeColor),
         e.CellBounds.X, e.CellBounds.Y);
       }
       e.Handled = true;
      }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 8:57
  • 12.    Как сделать Enter и Tab рабочими во время редактирования ячейки.

    Чтобы кнопки Enter и Tab работали во время редактирования ячейки вам нужно создать наследника DataGridView и переопределить метод ProcessDataGridViewKey для разрешения Enter и Tab. Ниже пример показывает, как это делается для Enter:

      class zxyDataGridView : DataGridView
      {
       protected override bool ProcessDataGridViewKey(KeyEventArgs e)
       {
        switch (e.KeyCode)
        {
         case Keys.Tab:
          return false;
         case Keys.Enter:
          {
           if (this.EditingControl != null)
           {
            if (this.EditingControl is TextBox)
            {
             TextBox tx = this.EditingControl as TextBox;
             int tmp = tx.SelectionStart;
             tx.Text = tx.Text.Insert(tx.SelectionStart,
                  Environment.NewLine);
             tx.SelectionStart = tmp + Environment.NewLine.Length;
             return true;
            }
           }
          }
          return false;
        }
        return base.ProcessDataGridViewKey(e);
       }
      }
    
    

    Для работы Tab необходимо разрешить свойство AcceptsTab для текстового поля редактирования ячейки:

      void dataGridView1_EditingControlShowing(object sender,DataGridViewEditingControlShowingEventArgs e)
      {
       if (e.Control is TextBox)
       {
        TextBox tb = e.Control as TextBox;
        tb.AcceptsTab = true;
       }
      }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:02
  • 13.    Как сделать отображении сетки DataGridView во всей видимой зоне?

    Если DataGridView больше размера зоны отображаемых данных, то незанятая область заливается серым фоном по умолчанию. Чтобы этого избежать можно сделать наследника DataGridView, в котором переопределить метод OnPaint для того, чтобы нарисовать сетку в области без данных.

    Ниже пример показывает, как это сделать:

         public class GridLineDataGridView : DataGridView
         {
           public GridLineDataGridView()
           {
             this.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
           }
           protected override void OnPaint(PaintEventArgs e)
           {
             base.OnPaint(e);
             int rowHeight = this.RowTemplate.Height;
             int h = this.ColumnHeadersHeight + rowHeight * this.RowCount;
             int imgWidth = this.Width - 2;
             Rectangle rFrame = new Rectangle(0, 0, imgWidth, rowHeight);
             Rectangle rFill = new Rectangle(1, 1, imgWidth - 2, rowHeight);
             Rectangle rowHeader = new Rectangle(2, 2, this.RowHeadersWidth - 3, rowHeight);
             Pen pen = new Pen(this.GridColor, 1);
             Bitmap rowImg = new Bitmap(imgWidth, rowHeight);
             Graphics g = Graphics.FromImage(rowImg);
             g.DrawRectangle(pen, rFrame);
             g.FillRectangle(new SolidBrush(this.DefaultCellStyle.BackColor), rFill);
             g.FillRectangle(new SolidBrush
              (this.RowHeadersDefaultCellStyle.BackColor), rowHeader);
             int w = this.RowHeadersWidth - 1;
             for (int j = 0; j < this.ColumnCount; j++)
             {
               g.DrawLine(pen, new Point(w, 0), new Point(w, rowHeight));
               w += this.Columns[j].Width;
             }
             int loop = (this.Height - h) / rowHeight;
             for (int j = 0; j < loop + 1; j++)
             {
               e.Graphics.DrawImage(rowImg, 1, h + j * rowHeight);
             }
           }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:06
  • 14.    Как запретить редактирование некоторых ячеек?

    Свойство ReadOnly указывает могут ли данные в ячейке быть изменены. Вы можете установить ReadOnly для отдельных ячеек или сделать всю строку или весь столбец только для чтения, установив соответственно DataGridViewRow.ReadOnly или DataGridViewColumn.ReadOnly. По умолчанию ячейка наследует значение свойства ReadOnly от строки или столбца, к которому она принадлежит.

    Это свойство запрещает редактирование ячейки пользователю, но не защищает от программного редактирования значения ячейки. Также оно не влияет на то, может ли пользователь удалять строки или столбцы.

     


    Для связи [mail]
    29 апреля 2011 г. 9:07
  • 15.    Как сделать недоступной (отключить) ячейку?

    Обычно понятие “отключить” означает то, что пользователь не может перейти к ячейке и вместо перехода он получает визуальный сигнал о недоступности действия. DataGridView не имеет встроенной поддержки, чтобы сделать недоступными ячейки. Ниже представлен непростой способ создания поддержки запрета ячейки. Пример расширяет DataGridViewButtonCell и реализует визуальное состояние “отключен” в соответствии с добавленным свойством для запрета ячейки:

        public class DataGridViewDisableButtonColumn : DataGridViewButtonColumn
         { 
          public DataGridViewDisableButtonColumn()
          { 
            this.CellTemplate = new DataGridViewDisableButtonCell();
          }
         }
     
        public class DataGridViewDisableButtonCell : DataGridViewButtonCell
         {
           private bool enabledValue;
           public bool Enabled
           {
             get
             {
               return enabledValue;
             }
             set
             {
               enabledValue = value;
             }
           }
     
           // Override the Clone method so that the Enabled property is copied.
           public override object Clone()
           {
             DataGridViewDisableButtonCell cell =
               (DataGridViewDisableButtonCell)base.Clone();
             cell.Enabled = this.Enabled;
             return cell;
           }
     
          // By default, enable the button cell.
           public DataGridViewDisableButtonCell()
           {
             this.enabledValue = true;
           }
     
          protected override void Paint(Graphics graphics,
             Rectangle clipBounds, Rectangle cellBounds, int rowIndex,
             DataGridViewElementStates elementState, object value,
             object formattedValue, string errorText,
             DataGridViewCellStyle cellStyle,
             DataGridViewAdvancedBorderStyle advancedBorderStyle,
             DataGridViewPaintParts paintParts)
           {
             // The button cell is disabled, so paint the border, 
            // background, and disabled button for the cell.
            if (!this.enabledValue)
            {
              // Draw the cell background, if specified.
              if ((paintParts & DataGridViewPaintParts.Background) ==
                DataGridViewPaintParts.Background)
              {
                SolidBrush cellBackground =
                  new SolidBrush(cellStyle.BackColor);
                graphics.FillRectangle(cellBackground, cellBounds);
                cellBackground.Dispose();
              }
     
              // Draw the cell borders, if specified.
              if ((paintParts & DataGridViewPaintParts.Border) ==
                DataGridViewPaintParts.Border)
              {
                PaintBorder(graphics, clipBounds, cellBounds, cellStyle,
                  advancedBorderStyle);
              }
     
              // Calculate the area in which to draw the button.
              Rectangle buttonArea = cellBounds;
              Rectangle buttonAdjustment =
                this.BorderWidths(advancedBorderStyle);
     
              buttonArea.X += buttonAdjustment.X;
              buttonArea.Y += buttonAdjustment.Y;
              buttonArea.Height -= buttonAdjustment.Height;
              buttonArea.Width -= buttonAdjustment.Width;
    
              // Draw the disabled button.        
              ButtonRenderer.DrawButton(graphics, buttonArea,
                PushButtonState.Disabled);
     
              // Draw the disabled button text. 
              if (this.FormattedValue is String)
              {
                TextRenderer.DrawText(graphics,
                  (string)this.FormattedValue,
                  this.DataGridView.Font,
                  buttonArea, SystemColors.GrayText);
              }
            }
            else
            {
              // The button cell is enabled, so let the base class 
              // handle the painting.
              base.Paint(graphics, clipBounds, cellBounds, rowIndex,
                elementState, value, formattedValue, errorText,
                cellStyle, advancedBorderStyle, paintParts);
            }
          }
        }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:13
  • 16.    Как показать элементы управления во всех ячейках независимо от редактирования?

    DataGridView поддерживает только отображение фактического элемента управления в момент редактирования ячейки. DataGridView не предназначен для отображения нескольких элементов управления. DataGridView рисует представление элемента управления, когда ячейка не редактируется. Представление может быть детализировано, как вы хотите. К примеру, DataGridViewButtonCell рисует кнопку вне зависимости находится ли ячейка в состоянии редактирования или нет.

    Вы можете добавить необходимые элементы управления с помощью метода DataGridView.Controls.Add() и задать их размер и месторасположение, чтобы расположить их в ячейках. Но отображать элементы управления во всех ячейках независимо от редактирования не имеет смысла.

     


    Для связи [mail]
    29 апреля 2011 г. 9:15
  • 17.    Как обработать событие SelectedIndexChanged?

    Иногда бывает полезно знать, когда пользователь выбрал другой элемент в ComboBox. Для обычного ComboBox нужно всего лишь подписаться на событие SelectedIndexChanged. Для DataGridViewComboBox нужно проделать примерно тоже, используя событие DataGridView.EditingControlShowing. Следующий пример показывает, как это делается, также там показано, как обойти множественные вызовы события:

        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
         {
           ComboBox cb = e.Control as ComboBox;
           if (cb != null)
           {
            // first remove event handler to keep from attaching multiple:
            cb.SelectedIndexChanged -= new EventHandler(cb_SelectedIndexChanged);
    
            // now attach the event handler
            cb.SelectedIndexChanged += new EventHandler(cb_SelectedIndexChanged);
          }
         }
     
        void cb_SelectedIndexChanged(object sender, EventArgs e)
         {
           MessageBox.Show("Selected index changed");
         }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:17
  • 18.    Как отобразить текст и иконку в одной ячейке?

    DataGridView не имеет какой-либо встроенной поддержки для отображения иконки и текса в одной ячейке. Но вы можете это сделать, используя различные события рисования, такие как CellPainting.

    Следующий пример расширяет DataGridViewTextColumn и ячейку для рисования изображения рядом с текстом. В примере свойство DataGridViewCellStyle.Padding используется для задания месторасположения текста, а Paint метод – для рисования иконки. Этот код можно упростить путем обработки события CellPainting и выполнением аналогичного кода.

       public class TextAndImageColumn : DataGridViewTextBoxColumn
        {
          private Image imageValue;
          private Size imageSize;
     
          public TextAndImageColumn()
          {
            this.CellTemplate = new TextAndImageCell();
          }
     
          public override object Clone()
          {
            TextAndImageColumn c = base.Clone() as TextAndImageColumn;
            c.imageValue = this.imageValue;
            c.imageSize = this.imageSize;
            return c;
          }
     
          public Image Image
          {
            get { return this.imageValue; }
            set
            {
              if (this.Image != value)
              {
                this.imageValue = value;
                this.imageSize = value.Size;
     
                if (this.InheritedStyle != null)
                {
                  Padding inheritedPadding = this.InheritedStyle.Padding;
                  this.DefaultCellStyle.Padding = new Padding(imageSize.Width,
                 inheritedPadding.Top, inheritedPadding.Right,
                 inheritedPadding.Bottom);
                }
              }
            }
          }
          private TextAndImageCell TextAndImageCellTemplate
          {
            get { return this.CellTemplate as TextAndImageCell; }
          }
          internal Size ImageSize
          {
            get { return imageSize; }
          }
        }
    public class TextAndImageCell : DataGridViewTextBoxCell
        {
          private Image imageValue;
          private Size imageSize;
     
          public override object Clone()
          {
            TextAndImageCell c = base.Clone() as TextAndImageCell;
            c.imageValue = this.imageValue;
            c.imageSize = this.imageSize;
            return c;
          }
     
          public Image Image
          {
            get
            {
              if (this.OwningColumn == null ||
            this.OwningTextAndImageColumn == null)
              {
     
                return imageValue;
              }
              else if (this.imageValue != null)
              {
                return this.imageValue;
              }
              else
              {
                return this.OwningTextAndImageColumn.Image;
              }
            }
            set
            {
              if (this.imageValue != value)
              {
                this.imageValue = value;
                this.imageSize = value.Size;
     
                Padding inheritedPadding = this.InheritedStyle.Padding;
                this.Style.Padding = new Padding(imageSize.Width,
                inheritedPadding.Top, inheritedPadding.Right,
                inheritedPadding.Bottom);
              }
            }
          }
          protected override void Paint(Graphics graphics, Rectangle clipBounds,
          Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState,
          object value, object formattedValue, string errorText,
          DataGridViewCellStyle cellStyle,
          DataGridViewAdvancedBorderStyle advancedBorderStyle,
          DataGridViewPaintParts paintParts)
          {
            // Paint the base content
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState,
              value, formattedValue, errorText, cellStyle,
              advancedBorderStyle, paintParts);
     
            if (this.Image != null)
            {
              // Draw the image clipped to the cell.
              System.Drawing.Drawing2D.GraphicsContainer container =
              graphics.BeginContainer();
     
              graphics.SetClip(cellBounds);
              graphics.DrawImageUnscaled(this.Image, cellBounds.Location);
     
              graphics.EndContainer(container);
            }
          }
     
          private TextAndImageColumn OwningTextAndImageColumn
          {
            get { return this.OwningColumn as TextAndImageColumn; }
          }
        }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:18
  • 19.    Как скрыть столбец?

    Иногда бывает нужно отобразить только некоторые из столбцов, которые доступны в DataGridView. Скрыть колонку можно 2мя способами – программно и в дизайнере.

    Для того чтобы скрыть программно, установите свойство Visible для нужной колонки в false.

    Для скрытия столбца через дизайнер:

    1. Выберите Правка столбцов (Edit Columns)
    2. В списке столбцов выберите нужный
    3. В свойствах столбца установите Visible в false

     


    Для связи [mail]
    29 апреля 2011 г. 9:20
  • 20.    Как пользователю запретить выполнять сортировку столбца?

    В DataGridView текстовые столбцы используют автоматическую сортировку по умолчанию, в то время как остальные типы столбцов не применяют сортировку по умолчанию. Иногда может потребоваться изменить эти умолчания. Для этого у столбца DataGridView есть свойство SortMode определяющее поведение сортировки.

     


    Для связи [mail]
    29 апреля 2011 г. 9:21
  • 21.    Как сделать сортировку по нескольким столбца

    По умолчанию DataGridView не предоставляет такого функционала. В зависимости используется ли привязка данных к DataGridView или нет, вы можете сделать поддержку сортировки по нескольким столбцам.

        21.1 DataGridView привязан к источнику данных

    Когда DataGridView привязан к источнику данный, то источник данных может быть отсортирован по нескольким столбцам и DataGridView отобразит эту сортировку. Но при этом символ сортировку будет применен только к первому столбца и свойство SortedColumn будет возвращать только первый отсортированный столбцел.

    Некоторые источники данных имеют встроенную поддержку сортировки по нескольким столбцам. Если источник данных реализует IBindingListView и имеет свойство Sort, то он поддерживает сортировку по нескольким столбцам. Чтобы показать, что сортировка выполнена по нескольким столбцам, нужно вручную задать свойство SortGlyphDirection для столбцов.

    Следующий пример использует DataTable и устанавливает сортировку по второму и третьему столбцам. Пример также показывает, как установить свойство SortGlyphDirection для столбцов. Пример предполагает, что на форме расположены DataGridView и есть компонент BindingSource:

     DataTable dt = new DataTable();
     dt.Columns.Add("C1", typeof(int));
     dt.Columns.Add("C2", typeof(string));
     dt.Columns.Add("C3", typeof(string));
     
     dt.Rows.Add(1, "1", "Test1");
     dt.Rows.Add(2, "2", "Test2");
     dt.Rows.Add(2, "2", "Test1");
     dt.Rows.Add(3, "3", "Test3");
     dt.Rows.Add(4, "4", "Test4");
     dt.Rows.Add(4, "4", "Test3");
     
     DataView view = dt.DefaultView;
     view.Sort = "C2 ASC, C3 ASC";
     bindingSource.DataSource = view;
     
     DataGridViewTextBoxColumn col0 = new DataGridViewTextBoxColumn();
     col0.DataPropertyName = "C1";
     dataGridView1.Columns.Add(col0);
     col0.SortMode = DataGridViewColumnSortMode.Programmatic;
     col0.HeaderCell.SortGlyphDirection = SortOrder.None;
     
     DataGridViewTextBoxColumn col1 = new DataGridViewTextBoxColumn();
     col1.DataPropertyName = "C2";
     dataGridView1.Columns.Add(col1);
     col1.SortMode = DataGridViewColumnSortMode.Programmatic;
     col1.HeaderCell.SortGlyphDirection = SortOrder.Ascending;
     
     DataGridViewTextBoxColumn col2 = new DataGridViewTextBoxColumn();
     col2.DataPropertyName = "C3";
     dataGridView1.Columns.Add(col2);
     col2.SortMode = DataGridViewColumnSortMode.Programmatic;
     col2.HeaderCell.SortGlyphDirection = SortOrder.Ascending;
    
    

         21.2 Непривязанный DataGridView

    Чтобы обеспечить поддержку сортировки по нескольким столбцам вы можете обработать событие SortCompare или вызывать перегруженный метод Sort(IComparer) для того, чтобы задать больше гибкости сортировке.

         21.2.1 Пользовательская сортировка, используя событие SortCompare

    Следующий пример кода демонстрирует пользовательскую сортировку, используя событие SortComparer. Сортируется выделенная колонка DataGridView и если в ней есть одинаковые значения, то используется дополнительная сортировка по столбцу ID.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Windows.Forms;
     
    class Form1 : Form
    {
     private DataGridView dataGridView1 = new DataGridView();
     
     // Establish the main entry point for the application.
     [STAThreadAttribute()]
     static void Main()
     {
      Application.EnableVisualStyles();
      Application.Run(new Form1());
     }
     
     public Form1()
     {
      // Initialize the form.
      // This code can be replaced with designer generated code.
      dataGridView1.AllowUserToAddRows = false;
      dataGridView1.Dock = DockStyle.Fill;
      dataGridView1.SortCompare += new DataGridViewSortCompareEventHandler(
       this.dataGridView1_SortCompare);
      Controls.Add(this.dataGridView1);
      this.Text = "DataGridView.SortCompare demo";
     
      PopulateDataGridView();
     }
     
     // Replace this with your own population code.
     public void PopulateDataGridView()
     {
      // Add columns to the DataGridView.
      dataGridView1.ColumnCount = 3;
     
      // Set the properties of the DataGridView columns.
      dataGridView1.Columns[0].Name = "ID";
      dataGridView1.Columns[1].Name = "Name";
      dataGridView1.Columns[2].Name = "City";
      dataGridView1.Columns["ID"].HeaderText = "ID";
      dataGridView1.Columns["Name"].HeaderText = "Name";
      dataGridView1.Columns["City"].HeaderText = "City";
     
      // Add rows of data to the DataGridView.
      dataGridView1.Rows.Add(new string[] { "1", "Parker", "Seattle" });
      dataGridView1.Rows.Add(new string[] { "2", "Parker", "New York" });
      dataGridView1.Rows.Add(new string[] { "3", "Watson", "Seattle" });
      dataGridView1.Rows.Add(new string[] { "4", "Jameson", "New Jersey" });
      dataGridView1.Rows.Add(new string[] { "5", "Brock", "New York" });
      dataGridView1.Rows.Add(new string[] { "6", "Conner", "Portland" });
     
      // Autosize the columns.
      dataGridView1.AutoResizeColumns();
     }
     
     private void dataGridView1_SortCompare(object sender,
      DataGridViewSortCompareEventArgs e)
     {
      // Try to sort based on the cells in the current column.
      e.SortResult = System.String.Compare(
       e.CellValue1.ToString(), e.CellValue2.ToString());
     
      // If the cells are equal, sort based on the ID column.
      if (e.SortResult == 0 && e.Column.Name != "ID")
      {
       e.SortResult = System.String.Compare(
        dataGridView1.Rows[e.RowIndex1].Cells["ID"].Value.ToString(),
        dataGridView1.Rows[e.RowIndex2].Cells["ID"].Value.ToString());
      }
      e.Handled = true;
     }
    }
    
    

        21.2.2 Произвольная сортировка, используя интерфейс IComparer

    Следующий пример кода демонстрирует пользовательскую сортировку используя перегруженный метод Sort(IComparer), который принимает реализация интерфейса IComparer, выполняющего сортировку по нескольким столбцам.

    using System;
    using System.Drawing;
    using System.Windows.Forms;
     
    class Form1 : Form
    {
     private DataGridView DataGridView1 = new DataGridView();
     private FlowLayoutPanel FlowLayoutPanel1 = new FlowLayoutPanel();
     private Button Button1 = new Button();
     private RadioButton RadioButton1 = new RadioButton();
     private RadioButton RadioButton2 = new RadioButton();
     
     // Establish the main entry point for the application.
     [STAThreadAttribute()]
     public static void Main()
     {
      Application.Run(new Form1());
     }
     
     public Form1()
     {
      // Initialize the form.
      // This code can be replaced with designer generated code.
      AutoSize = true;
      Text = "DataGridView IComparer sort demo";
     
      FlowLayoutPanel1.FlowDirection = FlowDirection.TopDown;
      FlowLayoutPanel1.Location = new System.Drawing.Point(304, 0);
      FlowLayoutPanel1.AutoSize = true;
     
      FlowLayoutPanel1.Controls.Add(RadioButton1);
      FlowLayoutPanel1.Controls.Add(RadioButton2);
      FlowLayoutPanel1.Controls.Add(Button1);
     
      Button1.Text = "Sort";
      RadioButton1.Text = "Ascending";
      RadioButton2.Text = "Descending";
      RadioButton1.Checked = true;
     
      Controls.Add(FlowLayoutPanel1);
      Controls.Add(DataGridView1);
     }
     
     protected override void OnLoad(EventArgs e)
     {
      PopulateDataGridView();
      Button1.Click += new EventHandler(Button1_Click);
     
      base.OnLoad(e);
     }
     
     // Replace this with your own code to populate the DataGridView.
     private void PopulateDataGridView()
     {
     
      DataGridView1.Size = new Size(300, 300);
     
      // Add columns to the DataGridView.
      DataGridView1.ColumnCount = 2;
     
      // Set the properties of the DataGridView columns.
      DataGridView1.Columns[0].Name = "First";
      DataGridView1.Columns[1].Name = "Last";
      DataGridView1.Columns["First"].HeaderText = "First Name";
      DataGridView1.Columns["Last"].HeaderText = "Last Name";
      DataGridView1.Columns["First"].SortMode =
       DataGridViewColumnSortMode.Programmatic;
      DataGridView1.Columns["Last"].SortMode =
       DataGridViewColumnSortMode.Programmatic;
     
      // Add rows of data to the DataGridView.
      DataGridView1.Rows.Add(new string[] { "Peter", "Parker" });
      DataGridView1.Rows.Add(new string[] { "James", "Jameson" });
      DataGridView1.Rows.Add(new string[] { "May", "Parker" });
      DataGridView1.Rows.Add(new string[] { "Mary", "Watson" });
      DataGridView1.Rows.Add(new string[] { "Eddie", "Brock" });
     }
     
     private void Button1_Click(object sender, EventArgs e)
     {
      if (RadioButton1.Checked == true)
      {
       DataGridView1.Sort(new RowComparer(SortOrder.Ascending));
      }
      else if (RadioButton2.Checked == true)
      {
       DataGridView1.Sort(new RowComparer(SortOrder.Descending));
      }
     }
     
     private class RowComparer : System.Collections.IComparer
     {
      private static int sortOrderModifier = 1;
     
      public RowComparer(SortOrder sortOrder)
      {
       if (sortOrder == SortOrder.Descending)
       {
        sortOrderModifier = -1;
       }
       else if (sortOrder == SortOrder.Ascending)
       {
        sortOrderModifier = 1;
       }
      }
     
      public int Compare(object x, object y)
      {
       DataGridViewRow DataGridViewRow1 = (DataGridViewRow)x;
       DataGridViewRow DataGridViewRow2 = (DataGridViewRow)y;
     
       // Try to sort based on the Last Name column.
       int CompareResult = System.String.Compare(
        DataGridViewRow1.Cells[1].Value.ToString(),
        DataGridViewRow2.Cells[1].Value.ToString());
     
       // If the Last Names are equal, sort based on the First Name.
       if (CompareResult == 0)
       {
        CompareResult = System.String.Compare(
         DataGridViewRow1.Cells[0].Value.ToString(),
         DataGridViewRow2.Cells[0].Value.ToString());
       }
       return CompareResult * sortOrderModifier;
      }
     }
    }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:29
  • 22.    Как реализовать пересортировку строк методом Drag and Drop?

    Поддержка Drag and Drop для перемещения строк не встроена в DataGridView, но следуя стандарту Drag and Drop вы легко можете добавить эту функциональность к DataGridView. Фрагмент кода ниже показывает, как вы можете достичь этого. Предполагается что на форме расположен DataGridView, который имеет имя dataGridView1, свойство AllowDrop установлено в true и DataGridView подписан на соответствующие события.

        private Rectangle dragBoxFromMouseDown;
        private int rowIndexFromMouseDown;
        private int rowIndexOfItemUnderMouseToDrop;
        private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
        {
          if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
          {
            // If the mouse moves outside the rectangle, start the drag.
            if (dragBoxFromMouseDown != Rectangle.Empty &&
              !dragBoxFromMouseDown.Contains(e.X, e.Y))
            {
     
              // Proceed with the drag and drop, passing in the list item.          
              DragDropEffects dropEffect = dataGridView1.DoDragDrop(
              dataGridView1.Rows[rowIndexFromMouseDown],
              DragDropEffects.Move);
            }
          }
        }
     
        private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
        {
          // Get the index of the item the mouse is below.
          rowIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).RowIndex;
     
          if (rowIndexFromMouseDown != -1)
          {
            // Remember the point where the mouse down occurred.
            // The DragSize indicates the size that the mouse can move
            // before a drag event should be started.        
            Size dragSize = SystemInformation.DragSize;
     
            // Create a rectangle using the DragSize, with the mouse position being
            // at the center of the rectangle.
            dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
                                    e.Y - (dragSize.Height / 2)),
                      dragSize);
          }
          else
            // Reset the rectangle if the mouse is not over an item in the ListBox.
            dragBoxFromMouseDown = Rectangle.Empty;
    
        }
     
        private void dataGridView1_DragOver(object sender, DragEventArgs e)
        {
          e.Effect = DragDropEffects.Move;
        }
     
        private void dataGridView1_DragDrop(object sender, DragEventArgs e)
        {
          // The mouse locations are relative to the screen, so they must be
          // converted to client coordinates.
          Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));
     
          // Get the row index of the item the mouse is below.
          rowIndexOfItemUnderMouseToDrop =
            dataGridView1.HitTest(clientPoint.X, clientPoint.Y).RowIndex;
     
          // If the drag operation was a move then remove and insert the row.
          if (e.Effect == DragDropEffects.Move)
          {
            DataGridViewRow rowToMove = e.Data.GetData(
              typeof(DataGridViewRow)) as DataGridViewRow;
            dataGridView1.Rows.RemoveAt(rowIndexFromMouseDown);
            dataGridView1.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rowToMove);
     
          }
        }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:31
  • 23.    Как сделать последний столбец так, чтобы он занимал все оставшееся свободное место DataGridView?

    Установив свойство AutoSizeMode для столбца в значение Fill, тем самым вы добьетесь того, что столбец будет растягиваться на всю оставшуюся зону DataGridView. По желанию можно установить минимальную ширину столбца, чтобы предотвратить сужение столбца. Это делается с помощью свойства MinimumWidth.

     


    Для связи [mail]
    29 апреля 2011 г. 9:32
  • 24.    Как сделать перенос текста в ячейке?

    По умолчанию текст в DataGridViewTextBoxCell не переносится. Но это поведение может быть изменено с помощью свойства WrapMode (DataGridView.DefaultCellStyle.WrapMode). Свойство принимает одно из значений перечисления DataGridViewTriState, которое задает что будет происходит с текстом.

     


    Для связи [mail]
    29 апреля 2011 г. 9:33
  • 25.    Как сделать так, чтобы столбец изображений не показывал стандартное “X” изображение?

    По умолчанию в ячейках столбца изображений null значения отображаются в виде стандартного “X” изображения. Вы можете запретить вывод этого изображения, задав null значение для свойства NullValue. Пример:

      this.dataGridViewImageColumn1.DefaultCellStyle.NullValue = null;
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:34
  • 26.    Как разрешить ввод текста в combobox ячейке?

    По умолчанию DataGridView не поддерживает ввод текста в DataGridViewComboBoxCell ячейках. Но если вам необходим такой функционал, то вы можете его включить следующим путем. Для начала нужно задать свойство DropDownStyle в DropDown для ComboBox ячейки. Второе, что нужно сделать, это добавлять введенные пользователем значения в коллекцию Items ComboBox-а. Иначе, если этого не сделать, то будет вызываться событие DataError. Наиболее лучшим событием для нового значения в коллекцию Items является событие CellValidating.

        private void dataGridView1_CellValidating(object sender,
             DataGridViewCellValidatingEventArgs e)
        {
          if (e.ColumnIndex == comboBoxColumn.DisplayIndex)
          {
            if (!this.comboBoxColumn.Items.Contains(e.FormattedValue))
            {
              this.comboBoxColumn.Items.Add(e.FormattedValue);
            }
          }
        }
     
        private void dataGridView1_EditingControlShowing(object sender,
            DataGridViewEditingControlShowingEventArgs e)
        {
          if (this.dataGridView1.CurrentCellAddress.X == comboBoxColumn.DisplayIndex)
          {
            ComboBox cb = e.Control as ComboBox;
            if (cb != null)
            {
              cb.DropDownStyle = ComboBoxStyle.DropDown;
            }
          }
        }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:35
  • 27.    Как в столбце с выпадающим списком отобразить подмножество значений, основанных на значении другого столбца с выпадающим списком?

    Иногда данные, которые вы хотите увидеть в DataGridView, получены на основании 2х связанных таблиц, например Категории и Подкатегории.  И вы хотите сделать так, чтобы пользователь мог выбрать подкатегорию на основе выбранной категории. Это возможно сделать, используя 2 столбца с выпадающими списками. Для этого необходимо создать 2 списка подкатегорий. Один список будет содержать все значения подкатегорий, в то время как к другому будет применяться фильтр во время редактирования пользователем ячейки подкатегорий. Это нужно потому что значение ячейки в столбце с выпадающем списке должно присутствовать в коллекции значений выпадающего списка, иначе будет вызвано событие DataError.

    Пример:

     private void Form1_Load(object sender, EventArgs e)
      {
       this.territoriesTableAdapter.Fill(this.northwindDataSet.Territories);
       this.regionTableAdapter.Fill(this.northwindDataSet.Region);
     
       // Setup BindingSource for filtered view.
       filteredTerritoriesBS = new BindingSource();
       DataView dv = new DataView(northwindDataSet.Tables["Territories"]);
       filteredTerritoriesBS.DataSource = dv;
     
      }
     
      private void dataGridView1_CellBeginEdit(object sender,
         DataGridViewCellCancelEventArgs e)
      {
       if (e.ColumnIndex == territoryComboBoxColumn.Index)
       {
        // Set the combobox cell datasource to the filtered BindingSource
        DataGridViewComboBoxCell dgcb = (DataGridViewComboBoxCell)dataGridView1
            [e.ColumnIndex, e.RowIndex];
        dgcb.DataSource = filteredTerritoriesBS;
     
        // Filter the BindingSource based upon the region selected
        this.filteredTerritoriesBS.Filter = "RegionID = " +
         this.dataGridView1[e.ColumnIndex - 1, e.RowIndex].Value.ToString();
       }
      }
     
      private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
      {
       if (e.ColumnIndex == this.territoryComboBoxColumn.Index)
       {
        // Reset combobox cell to the unfiltered BindingSource
        DataGridViewComboBoxCell dgcb = (DataGridViewComboBoxCell)dataGridView1
            [e.ColumnIndex, e.RowIndex];
        dgcb.DataSource = territoriesBindingSource; //unfiltered
     
        this.filteredTerritoriesBS.RemoveFilter();
       }
      }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:36
  • 28.    Как отобразить значок ошибки во время редактирования ячейки?

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

    Ниже пример демонстрирует, как задать ошибку, как задается смещение иконки с ошибкой и как выдать сообщение об ошибке при наведении мыши на ошибочную ячейку.

      private ToolTip errorTooltip;
      private Point cellInError = new Point(-2, -2);
      public Form1()
      {
        InitializeComponent();
        dataGridView1.ColumnCount = 3;
        dataGridView1.RowCount = 10;
      }
     
      private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
      {
        if (dataGridView1.IsCurrentCellDirty)
        {
          if (e.FormattedValue.ToString() == "BAD")
          {
            DataGridViewCell cell = dataGridView1[e.ColumnIndex, e.RowIndex];
            cell.ErrorText = "Invalid data entered in cell";
     
            // increase padding for icon. This moves the editing control
            if (cell.Tag == null)
            {
              cell.Tag = cell.Style.Padding;
              cell.Style.Padding = new Padding(0, 0, 18, 0);
              cellInError = new Point(e.ColumnIndex, e.RowIndex);
            }
            if (errorTooltip == null)
            {
              errorTooltip = new ToolTip();
              errorTooltip.InitialDelay = 0;
              errorTooltip.ReshowDelay = 0;
              errorTooltip.Active = false;
            }
     
            e.Cancel = true;
          }
        }
      }
     
      private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
      {
        if (dataGridView1.IsCurrentCellDirty && !String.IsNullOrEmpty(e.ErrorText))
        {
          // paint everything except error icon
          e.Paint(e.ClipBounds, DataGridViewPaintParts.All & 
                  ~(DataGridViewPaintParts.ErrorIcon));
     
          // now move error icon over to fill in the padding space
          GraphicsContainer container = e.Graphics.BeginContainer();
          e.Graphics.TranslateTransform(18, 0);
          e.Paint(this.ClientRectangle, DataGridViewPaintParts.ErrorIcon);
          e.Graphics.EndContainer(container);
     
          e.Handled = true;
        }
      }
     
      private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
      {
        if (dataGridView1[e.ColumnIndex, e.RowIndex].ErrorText != String.Empty)
        {
          DataGridViewCell cell = dataGridView1[e.ColumnIndex, e.RowIndex];
          cell.ErrorText = String.Empty;
          cellInError = new Point(-2,-2);
     
          // restore padding for cell. This moves the editing control
          cell.Style.Padding = (Padding)cell.Tag;
     
          // hide and dispose tooltip 
          if (errorTooltip != null)
          {
            errorTooltip.Hide(dataGridView1);
            errorTooltip.Dispose();
            errorTooltip = null;
          }
        }
      }
     
      // show and hide the tooltip for error
      private void dataGridView1_CellMouseMove(object sender, 
                  DataGridViewCellMouseEventArgs e)
      {
        if (cellInError.X == e.ColumnIndex &&
          cellInError.Y == e.RowIndex)
        {
          DataGridViewCell cell = dataGridView1[e.ColumnIndex, e.RowIndex];
     
          if (cell.ErrorText != String.Empty)
          {
            if (!errorTooltip.Active)
            {
              errorTooltip.Show(cell.ErrorText, dataGridView1, 1000);
            }
            errorTooltip.Active = true;
          }
        }
      }
     
      private void dataGridView1_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
      {
        if (cellInError.X == e.ColumnIndex &&
          cellInError.Y == e.RowIndex)
        {
          if (errorTooltip.Active)
          {
            errorTooltip.Hide(dataGridView1);
            errorTooltip.Active = false;
          }
        }
      }
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:38
  • 29.    Как вывести непривязанные данные вместе с привязанными данными?

    Данные для отображения в DataGridView как правило задаются через свойство DataSource, привязывая DataGridView к источнику данных. Но также можно отобразить столбцы, которые не привязаны к какому-либо источнику данных. Такие столбцы называются несвязанными. Вы можете использовать виртуальный режим DataGridView для отображения сразу привязанных и непривязанных данных.

    В следующем примере показано, как добавить checkbox столбец для того, чтобы пользователь мог выбрать строки для обработки. Выбранные строки хранятся в словаре по ID, для того чтобы была возможность сортировки, не теряя выбор строк.

      private System.Collections.Generic.Dictionary<int, bool> checkState;
      private void Form1_Load(object sender, EventArgs e)
      {
        dataGridView1.AutoGenerateColumns = false;
        dataGridView1.DataSource = customerOrdersBindingSource;
     
        // The check box column will be virtual.
        dataGridView1.VirtualMode = true;
        dataGridView1.Columns.Insert(0, new DataGridViewCheckBoxColumn());
     
        // Initialize the dictionary that contains the boolean check state.
        checkState = new Dictionary<int, bool>();
      }
      private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
      {
        // Update the status bar when the cell value changes.
        if (e.ColumnIndex == 0 && e.RowIndex != -1)
        {
          // Get the orderID from the OrderID column.
          int orderID = (int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;
          checkState[orderID] = (bool)dataGridView1.Rows[e.RowIndex].Cells[0].Value;
     
      }
     
      private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
      {
        // Handle the notification that the value for a cell in the virtual column
        // is needed. Get the value from the dictionary if the key exists.
     
        if (e.ColumnIndex == 0)
        {
          int orderID = (int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;
          if (checkState.ContainsKey(orderID))
          {
            e.Value = checkState[orderID];
          }
          else
            e.Value = false;
        }
     
      }
     
      private void dataGridView1_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)
      {
        // Handle the notification that the value for a cell in the virtual column
        // needs to be pushed back to the dictionary.
     
        if (e.ColumnIndex == 0)
        {
          // Get the orderID from the OrderID column.
    
          int orderID = (int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;
     
          // Add or update the checked value to the dictionary depending on if the 
          // key (orderID) already exists.
          if (!checkState.ContainsKey(orderID))
          {
            checkState.Add(orderID, (bool)e.Value);
          }
          else
            checkState[orderID] = (bool)e.Value;
        }
      }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:40
  • 30.    Как отобразить данные сразу с двух таблиц?

    DataGridView не предоставляет никаких новых функций, кроме виртуального режима, для достижения этого.  Вы можете использовать класс JoinView из статьи http://support.microsoft.com/default.aspx?scid=kb;en-us;325682. С помощью него можно объединить две или более таблиц вместе, а после привязать JoinView к DataGridView.

     


    Для связи [mail]
    29 апреля 2011 г. 9:41
  • 31.    Как отобразить master/details?

    Один из распространённых сценариев использования DataGridView – это отображение Master/Details формы, в которой отображаются 2 связанные таблицы. При выборе данных в основной таблице обновляются данные в связанной таблице, отображающей подробности.

    Реализация Master/Details формы проста при использовании связки DataGridView и BindingSource компонента. Пример ниже показывает 2 связанные таблицы из базы данных Northwind. Это таблицы Customers и Orders. В одном DataGridView отображаются клиенты, в другом подробности о заказах для выбранного клиента.

      using System;
      using System.Data;
      using System.Data.SqlClient;
      using System.Windows.Forms;
    
      public class Form1 : System.Windows.Forms.Form
      {
        private DataGridView masterDataGridView = new DataGridView();
        private BindingSource masterBindingSource = new BindingSource();
        private DataGridView detailsDataGridView = new DataGridView();
        private BindingSource detailsBindingSource = new BindingSource();
    
        [STAThreadAttribute()]
        public static void Main()
        {
          Application.Run(new Form1());
        }
    
        // Initializes the form.
        public Form1()
        {
          masterDataGridView.Dock = DockStyle.Fill;
          detailsDataGridView.Dock = DockStyle.Fill;
    
          SplitContainer splitContainer1 = new SplitContainer();
          splitContainer1.Dock = DockStyle.Fill;
          splitContainer1.Orientation = Orientation.Horizontal;
          splitContainer1.Panel1.Controls.Add(masterDataGridView);
          splitContainer1.Panel2.Controls.Add(detailsDataGridView);
    
          this.Controls.Add(splitContainer1);
          this.Load += new System.EventHandler(Form1_Load);
          this.Text = "DataGridView master/detail demo";
        }
    
        private void Form1_Load(object sender, System.EventArgs e)
        {
          // Bind the DataGridView controls to the BindingSource
          // components and load the data from the database.
          masterDataGridView.DataSource = masterBindingSource;
          detailsDataGridView.DataSource = detailsBindingSource;
          GetData();
    
          // Resize the master DataGridView columns to fit the newly loaded data.
          masterDataGridView.AutoResizeColumns();
    
          // Configure the details DataGridView so that its columns automatically
          // adjust their widths when the data changes.
          detailsDataGridView.AutoSizeColumnsMode =
            DataGridViewAutoSizeColumnsMode.AllCells;
        }
    
        private void GetData()
        {
          try
          {
            // Specify a connection string. Replace the given value with a 
            // valid connection string for a Northwind SQL Server sample
            // database accessible to your system.
            String connectionString =
              "Integrated Security=SSPI;Persist Security Info=False;" +
              "Initial Catalog=Northwind;Data Source=localhost";
            SqlConnection connection = new SqlConnection(connectionString);
    
            // Create a DataSet.
            DataSet data = new DataSet();
            data.Locale = System.Globalization.CultureInfo.InvariantCulture;
    
            // Add data from the Customers table to the DataSet.
            SqlDataAdapter masterDataAdapter = new
              SqlDataAdapter("select * from Customers", connection);
            masterDataAdapter.Fill(data, "Customers");
    
            // Add data from the Orders table to the DataSet.
            SqlDataAdapter detailsDataAdapter = new
              SqlDataAdapter("select * from Orders", connection);
            detailsDataAdapter.Fill(data, "Orders");
    
            // Establish a relationship between the two tables.
            DataRelation relation = new DataRelation("CustomersOrders",
              data.Tables["Customers"].Columns["CustomerID"],
              data.Tables["Orders"].Columns["CustomerID"]);
            data.Relations.Add(relation);
    
            // Bind the master data connector to the Customers table.
            masterBindingSource.DataSource = data;
            masterBindingSource.DataMember = "Customers";
    
            // Bind the details data connector to the master data connector,
    
            // using the DataRelation name to filter the information in the 
            // details table based on the current row in the master table. 
            detailsBindingSource.DataSource = masterBindingSource;
            detailsBindingSource.DataMember = "CustomersOrders";
          }
          catch (SqlException)
          {
            MessageBox.Show("To run this example, replace the value of the " +
              "connectionString variable with a connection string that is " +
              "valid for your system.");
          }
        }
      }
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:42
  • 32.    Как можно отобразить Master/Details в одном DataGridView?

    DataGridView не предоставляет никакой поддержки для показа Master/Details данных в том же DataGridView. Более ранний элемент управления System.Windows.Forms.DataGrid может быть решением этой проблемы.

     


    Для связи [mail]
    29 апреля 2011 г. 9:43
  • 33.    Как предотвратить сортировку?

    C помощью свойства DataGridView.SortMode вы можете запретить или изменить сортировку для того или иного столбца. В Visual Studio в визуальном редакторе можно щелкнуть правой кнопкой мыши на DataGridView, выбрать Edit Columns. Далее в списке выбрать нужный столбец и установить для него свойство SortMode в NotSortable, чтобы запретить сортировку.

     


    Для связи [mail]
    29 апреля 2011 г. 9:44
  • 34.    Как отправить обновления в базу данных, при нажатии кнопки на панели инструментов (toolstrip)?

    По умолчанию меню и панель инструментов не вызывают валидацию элементов управления. Валидация - это необходимая часть проверки и обновления данных для элементов управления с привязкой данных. После того как форма и все привязанные элементы управления будут проверены, нужно подтвердить завершение изменения данных. Наконец необходимо с помощью TableAdapter отправить изменения в базу данных.

    Пример:

        this.Validate();
        this.customersBindingSource.EndEdit();     
        this.customersTableAdapter.Update(this.northwindDataSet.Customers);
    
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:45
  • 35.    Как отобразить диалог подтверждения удаления строки?

    Когда пользователь выбрал строку в DataGridView и нажал кнопку удаления, то вызывается событие UserDeletingRow. В нем вы можете вывести диалог, уточняющий действия пользователя. Рекомендуется это делать только если строка не является новой строкой.

    Пример:

      if (!e.Row.IsNewRow)
      {
        DialogResult response = MessageBox.Show("Are you sure?", "Delete row?",
                   MessageBoxButtons.YesNo, 
                   MessageBoxIcon.Question, 
                   MessageBoxDefaultButton.Button2);
         if (response == DialogResult.No)
          e.Cancel = true;
      }
    

     


    Для связи [mail]
    29 апреля 2011 г. 9:46