Dialog Property access in Windows Forms.
People making the transition from legacy technologies to Windows Forms often ask about the right way to access properties in a form or dialog. MFC used a property exchange mechanism that was called to populate the controls in a dialog with their initial values and then again, when the editing was complete, to extract the information from the controls and replace the values in the dialog which could be read out by the calling code. Windows forms dispenses with that method but there is no clear strategy for performing a transfer of information from an application, to a dialog, then a control within the dialog and back out again. You are therefore left with a rule-of-thumb method that basically means "do it yourself"
Although there is no method set in stone, these guidelines will help you to create a consistent user-interface strategy which will be easy to maintain.
When creating a form the designer makes the controls private members of the form so accessing the control properties directly isn't possible unless you change the access of the objects to public. This is not recommended because the designer maintains the controls using a form of source-serialization so changing what the designer does can be a bad thing hence the directive never to change InitializeComponent manually.
Forms or dialogs need properties to be exposed that can be accessed by the calling program so that you can do something like...
C#
Dialog dlg=new Dialog();
dlg.TheValue=this.label1.Text;
if(dlg.ShowDialog()==DialogResult.OK)
this.label1.Text=dlg.TheValue;
VB
Dim dlg As New Dialog()
dlg.TheValue = Me.label1.Text
If dlg.ShowDialog() = DialogResult.OK Then
Me.label1.Text = dlg.TheValue
End If
Here you see that Dialog exposes a property called TheValue. Before the dialog is shown, the property is initialized with the data, the dialog is allowed to do whatever it needs to to present the information to the user and enable editing and then, depending on the return value of the dialog, the value is used or discarded.
Inside the dialog class a few things have to happen.
-
When the dialog is loaded, the information from the properties need to be copied into the controls on the form. This is done in the OnLoad override.
-
When the form is closed, the data from the controls needs to be copied to the public properties so that they can be read.
The dialog that handles this is shown in the following listing.
Show me code in C#
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace dialogAccess
{
/// <summary>
/// Summary description for Dialog.
/// </summary>
public class Dialog : System.Windows.Forms.Form
{
private string _theValue;
public string TheValue
{
get{return _theValue;}
set{_theValue=value;}
}
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public Dialog()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);
this.textBox1.Text=this._theValue;
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing (e);
if(this.DialogResult==DialogResult.Cancel)
return;
_theValue=this.textBox1.Text;
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(32, 24);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(192, 20);
this.textBox1.TabIndex = 0;
this.textBox1.Text = "textBox1";
//
// button1
//
this.button1.DialogResult = System.Windows.Forms.DialogResult.OK;
this.button1.Location = new System.Drawing.Point(32, 88);
this.button1.Name = "button1";
this.button1.TabIndex = 1;
this.button1.Text = "Ok";
//
// button2
//
this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button2.Location = new System.Drawing.Point(152, 88);
this.button2.Name = "button2";
this.button2.TabIndex = 1;
this.button2.Text = "Cancel";
//
// Dialog
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(266, 135);
this.Controls.Add(this.button1);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.button2);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "Dialog";
this.Text = "Dialog";
this.ResumeLayout(false);
}
#endregion
}
}
Show me code in VB
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Namespace dialogAccess
'/ <summary>
'/ Summary description for Dialog.
'/ </summary>
Public Class Dialog
Inherits System.Windows.Forms.Form
Private _theValue As String
Public Property TheValue() As String
Get
Return _theValue
End Get
Set
_theValue = value
End Set
End Property
Private textBox1 As System.Windows.Forms.TextBox
Private button1 As System.Windows.Forms.Button
Private button2 As System.Windows.Forms.Button
'/ <summary>
'/ Required designer variable.
'/ </summary>
Private components As System.ComponentModel.Container = Nothing
Public Sub New()
'
' Required for Windows Form Designer support
'
InitializeComponent()
End Sub 'New
'
' TODO: Add any constructor code after InitializeComponent call
'
'/ <summary>
'/ Clean up any resources being used.
'/ </summary>
Protected Overrides Sub Dispose(disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub 'Dispose
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
Me.textBox1.Text = Me._theValue
End Sub 'OnLoad
Protected Overrides Sub OnClosing(e As CancelEventArgs)
MyBase.OnClosing(e)
If Me.DialogResult = DialogResult.Cancel Then
Return
End If
_theValue = Me.textBox1.Text
End Sub 'OnClosing
#Region "Windows Form Designer generated code"
'/ <summary>
'/ Required method for Designer support - do not modify
'/ the contents of this method with the code editor.
'/ </summary>
Private Sub InitializeComponent()
Me.textBox1 = New System.Windows.Forms.TextBox()
Me.button1 = New System.Windows.Forms.Button()
Me.button2 = New System.Windows.Forms.Button()
Me.SuspendLayout()
'
' textBox1
'
Me.textBox1.Location = New System.Drawing.Point(32, 24)
Me.textBox1.Name = "textBox1"
Me.textBox1.Size = New System.Drawing.Size(192, 20)
Me.textBox1.TabIndex = 0
Me.textBox1.Text = "textBox1"
'
' button1
'
Me.button1.DialogResult = System.Windows.Forms.DialogResult.OK
Me.button1.Location = New System.Drawing.Point(32, 88)
Me.button1.Name = "button1"
Me.button1.TabIndex = 1
Me.button1.Text = "Ok"
'
' button2
'
Me.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel
Me.button2.Location = New System.Drawing.Point(152, 88)
Me.button2.Name = "button2"
Me.button2.TabIndex = 1
Me.button2.Text = "Cancel"
'
' Dialog
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(266, 135)
Me.Controls.Add(button1)
Me.Controls.Add(textBox1)
Me.Controls.Add(button2)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog
Me.Name = "Dialog"
Me.Text = "Dialog"
Me.ResumeLayout(False)
End Sub 'InitializeComponent
#End Region
End Class 'Dialog
End Namespace 'dialogAccess
Summary.
-
Create a public property of the type required such as string for text-boxes, bool for check-boxes and so-on.
-
When the dialog is created, initialize all the public properties with the initial values.
-
When the dialog's OnLoad override is called, update the private controls with the values from the public properties.
-
When the OnClosing override is called, transfer the contents of the private controls to the public properties.
-
Depending on the DialogResult, use or discard the dialog properties in the calling method.
Return to Windows Forms Tips and Tricks.
Copyright Bob Powell 2004. All rights reserved.
|