2011-02-23 9 views
6

En mi aplicación tengo un DataGridView que está diseñado para configurar algunas opciones. La idea es que pueda ingresar el texto que desee en la primera columna, pero si hace clic derecho, obtendrá valores respaldados explícitamente. Necesito que sea una caja de texto en lugar de una lista desplegable porque necesito apoyar la edición de configuraciones inválidas (o antiguas).¿Por qué mi menú contextual WinForms no aparece donde está el mouse?

Lo que quiero es que el usuario haga clic con el botón derecho en la columna del nombre del campo y tenga un menú contextual que sea válido según el tipo de configuración que sea. Por lo tanto, codifiqué el siguiente evento

private void grvFieldData_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     // If this is a right click on the Field name column, create a context menu 
     // with recognized options for that field 
     if (e.Button == MouseButtons.Right && grvFieldData.Columns[e.ColumnIndex].Name == "clmFieldName") 
     { 
      ContextMenu menu = new ContextMenu(); 

      if (_supportedDataGrids.ContainsKey((cmbDataGrid.SelectedItem as DataGridFieldList).GridName)) 
      { 
       // Loop through all the fields and add them to the context menu 
       List<string> fields = _supportedDataGrids[((cmbDataGrid.SelectedItem as DataGridFieldList).GridName)]; 
       fields.Sort(); 

       foreach (string field in fields) 
        menu.MenuItems.Add(new MenuItem(field)); 

       // Make sure there is at least one field before displaying the context menu 
       if (menu.MenuItems.Count > 0) 
        menu.Show(this, e.Location, LeftRightAlignment.Right); 
      } 
     } 
    } 

Esto funciona "correctamente", pero el menú contextual aparece en la parte superior del formulario, no donde el puntero del ratón. Si cambio la llamada Show() para usar el DataGridView en lugar del formulario, tengo el mismo problema, pero en cambio aparece en la esquina superior izquierda de la cuadrícula, no donde está el mouse.

Por extraño que parezca, si cambio este evento a un evento MouseClick (en lugar de un evento CellMouseclick) todo funciona y el menú de contexto aparece exactamente donde está el puntero del mouse. El problema con esta opción es que el usuario podría no estar haciendo clic con el botón derecho en la celda que está seleccionada actualmente, lo que significa que cuando hagan clic en un elemento del menú, la celda seleccionada cambiará y no la celda en la que hicieron clic.

¿Alguien tiene alguna pista de por qué los menús contextuales creados con CellMouseClick no se muestran en el lugar correcto?

Respuesta

17
menu.Show(this, e.Location, LeftRightAlignment.Right); 

El segundo argumento es la ubicación del ratón, en relación con el celular de esquina superior izquierda. Según lo programado, usted hace ese desplazamiento relativo desde este, el formulario, que hará que el menú aparezca en la esquina superior izquierda del formulario. Use el DGV ya que el primer argumento tampoco funciona, ahora está en la esquina superior izquierda de la cuadrícula.

un par de maneras de solucionar este problema, pero este es el camino más fácil:

Point pos = this.PointToClient(Cursor.Position); 
menu.Show(this, pos, LeftRightAlignment.Right); 

Puede reemplazar arbitrariamente este con grvFieldData.

+0

Heh, mi respuesta iba a ser un poco más complicada con un montón de agregar coordenadas X e Y. Desearía saber sobre Cursor.Position hace unas semanas! +1 por simplicidad! – Yetti

+0

¡Impresionante, eso funcionó como un encanto! 'Cursor.Position' es lo que me estaba perdiendo! – KallDrexx

1

tratan de utilizar PointToClient para conseguir lugar adecuado

+0

Nop. 'PointToClient (e.Location)' coloca el menú contextual en la parte superior de la pantalla, y 'PointToScreen (e.Location)' coloca el menú contextual en el medio del formulario por algún motivo. – KallDrexx

+0

grvFieldData.PointToClient (e.Location) – Stecya

+0

Mismo problema, incluso cuando cambio mi llamada 'this' a' grvFieldData': -/ – KallDrexx

1

No está mostrando en el lugar correcto, porque e.Location es la ubicación con respecto a la esquina superior izquierda del objeto padre, que en este caso es la propia célula. Las propiedades de ubicación siempre son relativas a su contenedor.

para obtener la posición del cursor del ratón en relación con la parte superior izquierda de la forma en sí misma, puede utilizar

this.PointToClient(Cursor.Position); 
+0

¿Cómo puedo obtener la ubicación de la celda en la que se hizo clic (las celdas no son controles, por lo tanto No puedo pasarlo a 'Show()') o la ubicación de la pantalla del mouse? – KallDrexx

+0

Ver mi respuesta editada. – MartW

1

He resuelto este problema ... ¡uno podría encontrar este método extraño, pero funciona bien!) Si queremos ver un menú contextual mientras presiona BTN derecho del ratón en la celda de DataGridView, y allí mismo, no en el medio de la pantalla o en otro lugar, tenemos que:

hacer algunas variables

int x=0; 
int y=0; 

hacer un evento 'MouseMove' para DataGridView1 lke que:

private void dataGridView1_MouseMove(object sender, MouseEventArgs e) 
{ 
    x = e.X; 
    y = e.Y; 
} 

y

private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
{ 
    if (e.Button == System.Windows.Forms.MouseButtons.Right) 
    { 
     contextMenuStrip1.Show(dataGridView1, x,y); 
    } 
} 

su bienvenida

+0

Esta solución tiene una sobrecarga innecesaria, ya que el usuario mueve su mouse sobre la cuadrícula (que supongo que sucederá con la suficiente frecuencia) y estará escribiendo constantemente en la memoria. El evento ya incluye la ubicación. –

3

En el evento DataGridView clic del ratón:

if e.button= mousebutton.right 
{ 
    contextmenu1.Show(MousePosition); 
} 
Cuestiones relacionadas