winforms 数据网格视图:如何将单元格设置为编辑模式?

qmb5sa22  于 2023-01-26  发布在  其他
关注(0)|答案(7)|浏览(231)

我需要以编程方式将单元格设置为编辑模式,我知道将该单元格设置为CurrentCell,然后调用方法BeginEdit(bool),这应该会发生,但在我的情况下,它不会发生。
我真的希望,我的DGV有几列,用户只能选择和编辑前两列。其他列已经是只读的,但用户可以选择他们,这是我不希望的。
所以我在想,告诉用户每次在单元格上完成书写时使用Tab键,然后选择第二个单元格,然后再次使用Tab键,它选择并开始编辑下一行的第一个单元格......
我该怎么做呢?

tag5nh1u

tag5nh1u1#

设置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控件的程序管理器编写,它涵盖了您可能希望使用该控件执行的大多数操作。

yruzcnhs

yruzcnhs2#

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

oxosxuxt3#

好吧,我会检查是否有列被设置为ReadOnly。我从来没有使用过BeginEdit,但也许有一些合法的用途。一旦您完成了dataGridView1.Columns[".."].ReadOnly = False;,非ReadOnly的字段应该是可编辑的。您可以使用DataGridView CellEnter事件来确定 * 输入了 * 哪个单元格然后在将编辑从前两列传递到下一组列之后打开对这些单元格的编辑,并关闭对最后两列的编辑。

5f0d552i

5f0d552i4#

我知道这个问题已经很老了,但是我想分享一些这个问题帮助我的演示代码。

  • 使用ButtonDataGridView创建窗体
  • 为button1注册Click事件
  • 为数据网格视图1注册CellClick事件
  • 将数据网格视图1的属性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);
                }
            }
        }
    }
}

请注意,列索引号可以通过多次按下按钮1来更改,因此我总是通过名称而不是索引值来引用列。我需要将大卫霍尔的答案合并到我的演示中,该演示已经有了ComboBox,因此他的答案非常有效。

a6b3iqyw

a6b3iqyw5#

我知道这是一个老问题,但没有一个答案对我有效,因为我想可靠地(总是能够)在可能执行其他事件时将单元格设置为编辑模式,如工具栏按钮点击,菜单选择,这些事件返回后可能会影响默认焦点。我最终需要一个计时器和调用。以下代码位于从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;
    }
  }
}
ngynwnxp

ngynwnxp6#

我终于找到了这个问题的答案,在我的例子中,我想在添加新行后选择特定的索引或项,但这应该适用于其他情况。
单元格本身并不包含combobox控件。DGV包含,它包含当前单元格的控件。因此,您必须将当前单元格设置为combo单元格,然后进入编辑模式,然后将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
rslzwgfq

rslzwgfq7#

这个问题是老问题了,但是建议的解决方案对我的情况没有帮助。加载表单时必须选择单元格。此选项不起作用:

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

如果您在“布局”事件中选择了单元格,则一切都将成功:

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

相关问题