2012-07-25 14 views
9

Estoy usando System.Windows.Forms.ContextMenu. Quiero que sea así cuando haces clic en algunos de los botones, no cierra el menú. Ahora mismo lo tengo funcionando donde cada vez que haces clic en uno, volverá a abrir el menú en la misma posición. El único problema es que se ve mal porque puede ver el menú parpadear. ¿Hay alguna forma mejor de hacer esto?C# WinForms - Mantenga un ContextMenu del cierre después de hacer clic en ciertos elementos

ContextMenu de WPF tiene la propiedad StaysOpen, pero la de Win Forms no. (¿Hay alguna forma de que pueda usar el ContextMenu de WPF?) No quiero usar ContextMenuStrip, que puede hacer esto, porque el ContextMenu se ve mucho mejor.

Editar:

No voy a marcar esto como una solución, ya que no es bueno para hacer esto. Si necesita hacer lo que mi pregunta requiere, una forma sería hacer un UserControl desde WPF, y luego colocar el objeto con el menú contextual en él, luego agregar el menú contextual a eso. Ahora, porque está en WPF, en los botones no desea cerrar el menú al hacer clic, establezca la propiedad StaysOpenOnClick en verdadero en el elemento de menú. Luego simplemente coloque este UserControl en su aplicación WinForms.

+0

Volví y acepté algunas respuestas de mis otras preguntas. En el momento en que los hice, no sabía que debías hacer eso. – Aidan

+0

No hay problema. Siempre es bueno aceptar respuestas correctas. De esa forma la comunidad puede construir reputación. – CodeLikeBeaker

Respuesta

4

No hay una buena manera de hacerlo con un control ContextMenu. Esa es solo una envoltura alrededor de los menús nativos Win32, por lo que se ve mucho mejor. Se dibuja utilizando las API de OS, al igual que los menús en todas las demás aplicaciones.

Compárelo con el control ContextMenuStrip, que es completamente dibujado por el framework en código C#. Parecía súper genial (supongo) cuando se lanzó por primera vez, cuando Windows y Office XP eran los productos más nuevos en los estantes. Cuando se lanzó Windows Vista, se volvió terriblemente obsoleto. La única ventaja que tiene tiene es que tiene un control mucho más fino sobre los menús. Por ejemplo, puede alojar controles personalizados en los menús, y puede evitar que el menú se cierre al hacer clic en uno de los elementos. Los menús nativos Win32 no tienen soporte para eso.

Por supuesto, es más que una omisión de supervisión o accidental. El deseo de mantener abierto un menú contextual después de que el usuario haya seleccionado algo es una buena pista de que su diseño es incorrecto. Tenga en cuenta que el objetivo de un menú contextual es brindarle al usuario un acceso rápido a las opciones contextualmente relevantes. Todo lo que tienen que hacer es hacer clic derecho (o presionar un botón especial en su teclado), y pueden ver un menú de opciones directamente relacionadas con lo que están trabajando o tratando de lograr. Al igual que un menú normal, se supone que pueden seleccionar una opción y hacer que el menú desaparezca.

En Windows, todos los menús son de "cierre automático". Si el menú debe ser persistente, no debe ser un menú en absoluto. Considere utilizar una barra de herramientas, una barra lateral o algún tipo de control personalizado en su lugar. Esos no están diseñados para desaparecer cuando se selecciona una de sus opciones y, por lo tanto, son ideales para mostrar opciones relacionadas que siempre deberían estar visibles.

Si un menú contextual en una aplicación no desapareció después de seleccionar una opción, consideraría que se trata de un error. Por lo menos, asumiría que mi selección no "tomó" e intenté hacer clic de nuevo.

No tengo la más mínima idea de por qué el equipo de WPF decidió proporcionar una opción de StaysOpen por sus menús de contexto, o por qué volvió a escribir su propia clase menú contextual en el primer lugar. ¿No aprendieron algo del equipo de WinForms después de haber hecho lo mismo?

La única forma de hacer lo que está pidiendo con el control ContextMenu (y por lo tanto los menús nativos) es un truco similar al que describe: almacena la posición previa del menú y después de seleccionar un comando , vuelva a mostrar el menú emergente en su ubicación anterior. Cualquiera que sea la cura que se le ocurra para el parpadeo (por ejemplo, congelar la pantalla y suprimir los repintados hasta que se vuelva a mostrar el menú contextual), casi se garantiza que será peor que la enfermedad.

+0

Gracias. Sé que no se "supone" que lo haga así, pero en mi situación, creo que funciona bien. Tengo un TreeView, en el cual cada nodo puede tener opciones booleanas asociadas. Tengo un menú contextual adjunto a cada nodo para establecer esas opciones, y no tengo ningún espacio en la ventana para botones o casillas de verificación reales. Además, las casillas de verificación deberían estar en fácil acceso al TreeView, no en una ventana emergente o algo así. – Aidan

+2

Un poco tarde, pero olvidé agregar: los botones en el ContextMenu son botones de casilla de verificación, y no quiero cerrar el menú mientras cambian el estado de verificación en los botones. Puedes ver que marque/desmarque, así que no creo que se vea como un error como dijiste. – Aidan

+1

Los menús contextuales no son particularmente detectables para los usuarios. Deben estar ahí para las personas que los conocen y desean usarlos, pero no deben formar el método principal de interacción con su aplicación. Mi recomendación sería * hacer * espacio para una pequeña barra de herramientas en la parte superior o inferior del control TreeView. –

15

Usted puede mantener su abra el menú contextual de esta manera:

private bool CloseContextMenu = true; //Class Variable 

continuación, agregue el MouseDown incluso a su elemento de menú contextual:

private void menu1ToolStripMenuItem_MouseDown(object sender, MouseEventArgs e) 
{ 
    CloseContextMenu = false; 
} 

A continuación, en su caso menú de cierre contexto:

private void contextMenuStrip1_Closing(object sender, ToolStripDropDownClosingEventArgs e) 
{ 
    e.Cancel = !CloseContextMenu; 
    CloseContextMenu = true; 
} 

Luego puede agregar CloseContextMenu = false a cualquiera de los eventos de menú que desee.

Espero que esto ayude.

+1

Gracias, pero estoy hablando de un ContextMenu, no de un ContextMenuStrip. Lamentablemente, el evento de cierre del ContextMenu no tiene un e.Cancel (al menos no que yo sepa). – Aidan

+0

Esto se puede simplificar a: 'contextMenuStrip1.Closing + = (s, e) => e.Cancel = e.CloseReason == ToolStripDropDownCloseReason.ItemClicked;' Aun así, no funciona para 'ContextMenu'. –

-1

acabo añade

ContextMenuStrip1.Show(); 

en mi evento de clic. Cuando hago clic en el menú contextual, se cierra, pero se abre de inmediato, por lo que permanece efectivamente abierto.

Cuestiones relacionadas