2010-03-06 16 views
5

seguidor de joelonsoftware desde hace mucho tiempo, 1er póster de stackoverflow.Acceder a la propiedad de texto del control después del formulario principal Dispose() 'd?

Quiero saber "cómo con seguridad" Puedo hacer lo siguiente (C#):

Form formDlg = new Form(); 
TextBox box = new TextBox(); 
formDlg.Controls.Add(box); 
formDlg.ShowDialog(); 
formDlg.Dispose(); 
string sUserEntered = box.Text; // After parent Dispose'd! 

En la práctica, esto (al parecer) que funciona, porque cuadro (como control) tiene una private texto campo (una cadena) que utiliza para implementar su propiedad Text después de que se destruye su identificador de ventana.

No me satisfará la respuesta general de que "no se puede acceder a un objeto una vez que está Dispuesto" porque (1) no encuentro ninguna prohibición general en los documentos de MS, (2) estoy no acceder a un recurso no administrado, y (3) este código no arroja ninguna excepción (incluida ObjectDisposedException).

Me gustaría hacer esto para poder crear y usar un método combinado "ShowAndDispose" para reducir el riesgo de olvidarme de llamar siempre a Dispose() después de ShowDialog().

Para complicar, el comportamiento cambia en el depurador. Si me rompo antes de tirar(); luego Quick Watch box y profundizar en su Control clase base; luego pasa el paso Dispose(); luego box.Text regresa ""! En el cuadro de otros escenarios, Text devuelve el texto ingresado por el usuario.

+0

¿Por qué forzarías un Dispose en el formulario? Especialmente cuando no estás accediendo a recursos no administrados. Deje que Framework/GC se encargue de eso. EDITAR: Tengo la sensación de que tienes una situación mucho más complicada que el código anterior. – Zyphrax

+0

No solo eso, ¿por qué acceder a un cuadro de texto que está en un formulario que está dispuesto() ...? ¿Por qué querrías hacer eso? No tiene sentido para mi? Eso es como punteros en C, puedes malloc un puntero, hacer algunas cosas con él, luego liberarlo, luego desreferenciar el puntero después de ser liberado! – t0mm13b

+0

Zyphrax: un formulario contiene muchos recursos no administrados, 1 por control. –

Respuesta

2

Es un detalle de implementación que este código se ejecuta sin problemas . La propiedad Control está almacenada en caché por la clase Control, por lo que eliminar el TextBox no provoca una excepción ObjectDisposed.

Es bastante raro, por cierto, que un montón de getters y setters de propiedades de control generen un mensaje de Windows para solicitar al control Window nativo el valor de la propiedad. Obtendrá un kaboom en esos porque la propiedad Handle ya no es válida. También es notable que el ajustador de propiedades de texto actualiza el valor en caché pero también genera un mensaje de ventana para actualizar el control nativo. Kaboom aquí.

Supongo que esto es solo de interés general, nunca use un código como ese en su programa. Bueno, lo descubrirías lo suficientemente rápido.

+0

Thx, la mejor respuesta todavía. –

1

El escenario depurador me hace pensar que lo que haces no es fiable, para probar que al menos debe intentar esto:

formDlg.Dispose(); 
Application.DoEvents(); 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 
string sUserEntered = box.Text; // After parent Dispose'd! 
+0

Bien, lo intenté, todavía "funciona". Las variables formDlg y box todavía están dentro del alcance, por lo que no esperaría que GC afectara a sus objetos. Thx de todos modos. –

+0

@Conrad: Todavía dudo, ¿por qué desaparecería el texto en el depurador? –

+0

Hice algunas pruebas y el texto desaparece con todas las variaciones que probé. Hasta que coloqué el valor del texto del control en una propiedad pública, no pude recuperar el valor del texto en mi formulario principal; consulte mi respuesta a continuación. – IAbstract

2

Usted puede utilizar la instrucción 'utilizar' para asegurar un objeto obtiene dispuesto cuando ya terminaste con él:

using(Form frmDialog = new Form()) 
{ 
    //Do stuff 
} 

frmDialog quedarán eliminados una vez que el bloque haya funcionado, creo.

+0

Realmente no cambia su pregunta. En comparación, 'string sUserEntered = box.Text;' vendrá después del bloque de uso. – Zyphrax

+0

Sí, esa es una mejor solución que un método ShowAndDispose(). –

+1

@ Zyphrax, no, resolvería el problema del OP sobre olvidar el Dispose y, por supuesto, el cuadro. El código de texto iría dentro del uso. –

0

puse el valor sUserEntered en una propiedad pública por lo que se podría tener acceso:

public string UserInput 
    { 
     get; 
     set; 
    } 

    public frmDialog() 
    { 
     // 
     // The InitializeComponent() call is required for Windows Forms designer support. 
     // 
     InitializeComponent(); 

     // 
     // TODO: Add constructor code after the InitializeComponent() call. 
     // 
    } 

    void Button1Click(object sender, EventArgs e) 
    { 
     UserInput = userInput.Text; 
     this.Dispose(); 
    } 

Luego, en mi formulario principal:

 using (dialog = new frmDialog()) 
     { 
      dialog.ShowDialog(); 
      stringUserInput.Text = dialog.UserInput; 
     }; 
+0

Thx, sé que puedo hacer eso, crear una clase completamente nueva es mucho más código adicional de lo que quiero. –

0

Se me ocurre que puedo crear & use una clase derivada de formulario con un método BeginShowDialog() que llama a ShowDialog(), y un método EndShowDialog() que llama a Dispose(). El "Begin" en el nombre del método hará que la necesidad de la llamada "End" sea más obvia.

Extraño la destrucción determinada de C++ de los lugareños al salir del alcance.

+0

Aún tendría que envolverlo en un bloque try/finally, por lo que la ganancia sobre el uso es discutible. –

+0

Me saltearé el intento/finalmente. En el caso de Never-happens-in-the-world que lanza ShowDialog(), viviré con la fuga de recursos. –

+0

No estoy de acuerdo con que "usando" "resuelva" el problema que deseo abordar, que nunca se olvide, por los cientos de clases que uso, cuándo/si es necesario eliminar cada una de ellas. Si no recuerdo eso, no recordaré usar "usar" para esa clase mejor de lo que recordaré llamar Dispose(). –

Cuestiones relacionadas