2009-11-29 71 views
27

Necesito configurar programáticamente una celda en el modo de edición. Sé que establecer esa celda como CurrentCell y luego llamar al método BeginEdit (bool), debería suceder, pero en mi caso, no es así.Datagridview: ¿Cómo establecer una celda en modo de edición?

Realmente quiero eso, con mi DGV con varias columnas, el usuario SÓLO puede seleccionar y editar los dos primeros. Las otras columnas ya son de solo lectura, pero el usuario puede seleccionarlas, y eso es lo que no quiero.

Así que estaba pensando, dirá al usuario cada vez que TAB se ha terminado de escribir en la celda, a continuación, seleccione la segunda celda, a continuación, la ficha de nuevo y seleccionar y comenzar a editar primera celda de la fila siguiente ...

¿Cómo puedo hacer esto?

Respuesta

61

Configurando el CurrentCell y llamando al BeginEdit(true) funciona bien para mí.

El siguiente código muestra un eventHandler para el evento KeyDown que establece que una celda sea editable.

Mi ejemplo solo implementa una de las anulaciones de tecla presionadas pero, en teoría, las demás deberían funcionar igual. (Y siempre estoy de ajustar la [0] [0] celular para ser editable pero cualquier otra célula debería funcionar)

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);    
     } 
    } 

Si no ha encontrado previamente, el DataGridView FAQ es un gran recurso, escrito por el administrador de programa para el control DataGridView, que cubre la mayor parte de lo que podría querer hacer con el control.

+0

Gracias ... En primer lugar yo estaba tratando de utilizar el evento SelectionChange, y haciendo un trabajo duro (y uggly también) para evitar el desbordamiento de pila, ya que la selección cambia everytimes se dispara de nuevo. Pero ahora, me gusta más su solución ... Y gracias +1 por las preguntas frecuentes. Estoy más acostumbrado a web en lugar de winforms, pero de todos modos es bueno saberlo. Gracias! – josecortesp

+1

Esto es exactamente lo que necesitaba. Más o menos ... :) De hecho, estaba tratando de actualizar los contenidos de las celdas desde fuera de la grilla que estaba vinculada a una fuente de datos. Podría poner los nuevos valores en la pantalla, pero el botón Guardar estaba guardando los valores anteriores. Necesitaba poner CurrentCell antes y EndEdit() después de actualizar los valores. Tu respuesta me puso totalmente en el camino correcto. ¡Gracias! – BoltBait

+0

Evité la necesidad de hacer una pregunta similar - ty – IbrarMumtaz

2

Bueno, yo verificaría si alguna de sus columnas está configurada como ReadOnly. Nunca tuve que usar BeginEdit, pero tal vez haya algún uso legítimo. Una vez que haya hecho dataGridView1.Columns[".."].ReadOnly = False;, los campos que no son ReadOnly deben ser editables. Puede usar el evento DataGridView CellEnter para determinar qué celda fue ingresada y luego activar la edición en esas celdas después de haber pasado la edición de las dos primeras columnas al siguiente conjunto de columnas y desactivar la edición en las dos últimas columnas.

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

Sé que esta pregunta es bastante antigua, pero pensé que compartiría un código de demostración con el que esta pregunta me ayudó.

  • Crear un formulario con un Button y una DataGridView
  • El registro de un evento Click para botón1
  • Registra un evento CellClick para DataGridView1
  • propiedad
  • de Set DataGridView1 EditMode-EditProgrammatically
  • Pegue el código siguiente en Formulario1:
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); 
       } 
      } 
     } 
    } 
} 

Tenga en cuenta que los números de índice de la columna pueden cambiar al presionar varios botones del botón uno, por lo que siempre me refiero a las columnas por nombre y no por valor de índice. Necesitaba incorporar la respuesta de David Hall a mi demo que ya tenía ComboBoxes, por lo que su respuesta funcionó muy bien.

0

Sé que esta es una pregunta antigua, pero ninguna de las respuestas funcionó para mí, porque quería establecer de manera confiable (siempre podrá) la célula en modo de edición cuando posiblemente se ejecuten otros eventos como botones de la barra de herramientas, selecciones de menú , etc. que pueden afectar el enfoque predeterminado después de que esos eventos regresen. Terminé necesitando un temporizador e invoco. El siguiente código está en un nuevo componente derivado de DataGridView. Este código me permite simplemente hacer una llamada al myXDataGridView.CurrentRow_SelectCellFocus(myDataPropertyName); en cualquier momento que desee establecer arbitrariamente una celda de datos en el modo de edición (suponiendo que la celda no está en el modo ReadOnly).

// 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; 
    } 
    } 
} 
Cuestiones relacionadas