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 Ramuseco Limited 2004. All rights reserved.