簡體   English   中英

Datagridview:如何將單元格設置為編輯模式?

[英]Datagridview: How to set a cell in editing mode?

我需要以編程方式將單元格設置為編輯模式。 我知道將該單元格設置為 CurrentCell,然后調用方法 BeginEdit(bool),它應該發生,但在我的情況下,它不會發生。

我真的很想要,我的 DGV 有幾列,用戶只能 select 並且還可以編輯前兩列。 其他列已經是只讀的,但用戶可以 select 它們,這是我不想要的。

所以我在想,每次在單元格上寫完時告訴用戶 TAB,然后是第二個單元格 select,然后再次選擇 select 並開始編輯下一行的第一個單元格...

我怎樣才能做到這一點?

設置CurrentCell然后調用BeginEdit(true)對我來說效果很好。

以下代碼顯示了KeyDown事件的 eventHandler,該事件將單元格設置為可編輯。

我的示例僅實現了所需的按鍵覆蓋之一,但理論上其他的應該相同。 (我總是將 [0][0] 單元格設置為可編輯,但任何其他單元格都應該可以工作)

    private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Tab && dataGridView1.CurrentCell.ColumnIndex == 1)
        {
            e.Handled = true;
            DataGridViewCell cell = dataGridView1.Rows[0].Cells[0];
            dataGridView1.CurrentCell = cell;
            dataGridView1.BeginEdit(true);               
        }
    }

如果您以前沒有找到它, DataGridView FAQ是一個很好的資源,由 DataGridView 控件的程序經理編寫,它涵蓋了您可能想用該控件執行的大部分操作。

private void DgvRoomInformation_CellEnter(object sender, DataGridViewCellEventArgs e)
{
  if (DgvRoomInformation.CurrentCell.ColumnIndex == 4)  //example-'Column index=4'
  {
    DgvRoomInformation.BeginEdit(true);   
  }
}

好吧,我會檢查您的任何列是否設置為ReadOnly 我從來沒有使用過BeginEdit,但也許有一些合法的用途。 一旦你完成了dataGridView1.Columns[".."].ReadOnly = False; ,非ReadOnly字段應該是可編輯的。 您可以使用 DataGridView CellEnter事件來確定輸入了哪個單元格,然后在將編輯從前兩列傳遞到下一組列並關閉對最后兩列的編輯后,打開對這些單元格的編輯。

我知道這個問題已經很老了,但我想我會分享一些這個問題對我有幫助的演示代碼。

  • 創建一個帶有ButtonDataGridView的表單
  • 為 button1 注冊一個Click事件
  • 為 DataGridView1 注冊一個CellClick事件
  • EditProgrammatically將 DataGridView1 的屬性EditMode設置為EditProgrammatically
  • 將以下代碼粘貼到 Form1 中:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        DataTable m_dataTable;
        DataTable table { get { return m_dataTable; } set { m_dataTable = value; } }

        private const string m_nameCol = "Name";
        private const string m_choiceCol = "Choice";

        public Form1()
        {
            InitializeComponent();
        }

        class Options
        {
            public int m_Index { get; set; }
            public string m_Text { get; set; }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            table = new DataTable();
            table.Columns.Add(m_nameCol);
            table.Rows.Add(new object[] { "Foo" });
            table.Rows.Add(new object[] { "Bob" });
            table.Rows.Add(new object[] { "Timn" });
            table.Rows.Add(new object[] { "Fred" });

            dataGridView1.DataSource = table;

            if (!dataGridView1.Columns.Contains(m_choiceCol))
            {
                DataGridViewTextBoxColumn txtCol = new DataGridViewTextBoxColumn();
                txtCol.Name = m_choiceCol;
                dataGridView1.Columns.Add(txtCol);
            }

            List<Options> oList = new List<Options>();
            oList.Add(new Options() { m_Index = 0, m_Text = "None" });
            for (int i = 1; i < 10; i++)
            {
                oList.Add(new Options() { m_Index = i, m_Text = "Op" + i });
            }

            for (int i = 0; i < dataGridView1.Rows.Count - 1; i += 2)
            {
                DataGridViewComboBoxCell c = new DataGridViewComboBoxCell();

                //Setup A
                c.DataSource = oList;
                c.Value = oList[0].m_Text;
                c.ValueMember = "m_Text";
                c.DisplayMember = "m_Text";
                c.ValueType = typeof(string);

                ////Setup B
                //c.DataSource = oList;
                //c.Value = 0;
                //c.ValueMember = "m_Index";
                //c.DisplayMember = "m_Text";
                //c.ValueType = typeof(int);

                //Result is the same A or B
                dataGridView1[m_choiceCol, i] = c;
            }
        }

        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
            {
                if (dataGridView1.CurrentCell.ColumnIndex == dataGridView1.Columns.IndexOf(dataGridView1.Columns[m_choiceCol]))
                {
                    DataGridViewCell cell = dataGridView1[m_choiceCol, e.RowIndex];
                    dataGridView1.CurrentCell = cell;
                    dataGridView1.BeginEdit(true);
                }
            }
        }
    }
}

請注意,列索引號可能會因多次按下按鈕一而發生變化,因此我總是按名稱而不是索引值來引用列。 我需要將 David Hall 的答案合並到我已經有 ComboBoxes 的演示中,因此他的答案非常有效。

我知道這是一個老問題,但沒有一個答案對我有用,因為我想在可能執行其他事件(如工具欄按鈕單擊、菜單選擇等)時可靠地(始終能夠)將單元格設置為編輯模式。這些事件返回后可能會影響默認焦點。 我最終需要一個計時器並調用。 以下代碼位於派生自 DataGridView 的新組件中。 這段代碼允許我簡單地調用myXDataGridView.CurrentRow_SelectCellFocus(myDataPropertyName); 任何時候我想將數據綁定單元格任意設置為編輯模式(假設單元格不處於只讀模式)。

// If the DGV does not have Focus prior to a toolbar button Click, 
// then the toolbar button will have focus after its Click event handler returns.
// To reliably set focus to the DGV, we need to time it to happen After event handler procedure returns.

private string m_SelectCellFocus_DataPropertyName = "";
private System.Timers.Timer timer_CellFocus = null;

public void CurrentRow_SelectCellFocus(string sDataPropertyName)
{
  // This procedure is called by a Toolbar Button's Click Event to select and set focus to a Cell in the DGV's Current Row.
  m_SelectCellFocus_DataPropertyName = sDataPropertyName;
  timer_CellFocus = new System.Timers.Timer(10);
  timer_CellFocus.Elapsed += TimerElapsed_CurrentRowSelectCellFocus;
  timer_CellFocus.Start();
}


void TimerElapsed_CurrentRowSelectCellFocus(object sender, System.Timers.ElapsedEventArgs e)
{
  timer_CellFocus.Stop();
  timer_CellFocus.Elapsed -= TimerElapsed_CurrentRowSelectCellFocus;
  timer_CellFocus.Dispose();
  // We have to Invoke the method to avoid raising a threading error
  this.Invoke((MethodInvoker)delegate
  {
    Select_Cell(m_SelectCellFocus_DataPropertyName);
  });
}


private void Select_Cell(string sDataPropertyName)
{
  /// When the Edit Mode is Enabled, set the initial cell to the Description
  foreach (DataGridViewCell dgvc in this.SelectedCells) 
  {
    // Clear previously selected cells
    dgvc.Selected = false; 
  }
  foreach (DataGridViewCell dgvc in this.CurrentRow.Cells)
  {
    // Select the Cell by its DataPropertyName
    if (dgvc.OwningColumn.DataPropertyName == sDataPropertyName)
    {
      this.CurrentCell = dgvc;
      dgvc.Selected = true;
      this.Focus();
      return;
    }
  }
}

我終於找到了這個問題的答案。 就我而言,我想在添加新行后選擇特定索引或項目,但這應該適用於其他情況。

單元格不包含組合框控件。 DGV 確實如此,它擁有當前單元格的控制權。 因此,您必須將當前單元格設為組合單元格,然后進入編輯模式,然后將 dgv 控件轉換為 ComboBox,然后您將可以訪問 selectedIndex 和 selectedItem 方法

Dim rowIndex = myDgv.Rows.Add()
myDgv.ClearSelection()
myDgv.CurrentCell = myDgv.Rows(rowIndex).Cells("colName")
myDgv.BeginEdit(True)
Dim myCombo as ComboBox = CType(myDgv.EditingControl, ComboBox)
myCombo.SelectedIndex = 3

這個問題很老,但建議的解決方案對我的情況沒有幫助。 加載表單時需要 select 單元格。 此選項不起作用:

private void FOperations_Load(object sender, EventArgs e)
{
  dgvOperations.CurrentCell = dgvOperations[nameof(Operation.DisplayName), 0];
  dgvOperations.Select();
}

如果在“Layout”事件中進行單元格選擇,那么一切都成功了:

private void dgvOperation_Layout(object sender, LayoutEventArgs e)
{
  dgvOperations.CurrentCell = dgvOperations[nameof(Operation.DisplayName), 0];
  dgvOperations.Select();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM