6.5 Apply Button
All dialog
An Apply button typically is disabled, i.e., grayed out, when the dialog first opens. As soon as any change is made in one of the dialog controls, the button is enabled. Clicking the Apply button makes available to the parent form all the changes made in the dialog box, but
You might be tempted to implement the Apply button by creating a public method in the parent Form class that
This is not a clean way to implement an Apply button, however, because the dialog box class needs to know too much about the parent class. Also, if other classes invoke your dialog box, the dialog box must know their
A preferable design, which decouples the dialog class from the calling class, is to have the Dialog Box raise an event when the Apply button is clicked. The Apply event would be handled by the parent form and any other interested classes. With this event-driven design, the Dialog box and the parent class can be modified independently of one another; they are associated only through the indirection of publishing and subscribing to the Apply event.
The following example
Open Visual Studio .NET and create a new Windows Application project called DialogapplyEvent in the language of your choice. Drag a Button control onto the form. Name the button btnCreate and change the Text property to Create Dialog Box. Resize it as necessary to make it look good. Drag a Label control onto the form and
Right-click
Example 6-5. DialogDemo class using an event in C#
// Dialog box class
private class DialogDemo : Form
{
private Button btnApply;
private TextBox txt;
public event EventHandler ClickApply;
public DialogDemo( )
{
Text = "Apply Dialog Demo";
FormBorderStyle = FormBorderStyle.FixedDialog;
BackColor = System.Drawing.Color.Aquamarine;
ControlBox = false;
MaximizeBox = false;
MinimizeBox = false;
ShowInTaskbar = false;
Size = new Size(400,200);
StartPosition = FormStartPosition.CenterScreen;
// Create the OK button
Button btnOK = new Button( );
btnOK.Text = "OK";
btnOK.DialogResult = DialogResult.OK;
btnOK.Location = new Point(50,50);
btnOK.TabIndex = 0;
btnOK.Click += new EventHandler(applyButtonOnClick);
Controls.Add(btnOK);
// Create the Apply button
btnApply = new Button( );
btnApply.Text = "Apply";
btnApply.Location = new Point(150,50);
btnApply.TabIndex = 1;
btnApply.Enabled = false;
btnApply.Click += new EventHandler(applyButtonOnClick);
Controls.Add(btnApply);
// Create the Cancel button
Button btnCancel = new Button( );
btnCancel.Text = "Cancel";
btnCancel.DialogResult = DialogResult.Cancel;
btnCancel.Location = new Point(250,50);
btnCancel.TabIndex = 2;
Controls.Add(btnCancel);
// create input text box
txt = new TextBox( );
txt.Size = new Size(100,15);
txt.Location = new Point(150,15);
txt.TextChanged += new EventHandler(TextBoxChanged);
Controls.Add(txt);
} // close DialogDemo constructor
private void TextBoxChanged(object sender, EventArgs e)
{
TextBox txt = (TextBox)sender;
DialogDemo dlg = (DialogDemo)txt.Parent;
dlg.EnableapplyButton = true;
}
public bool EnableapplyButton
{
get {return btnApply.Enabled; }
set {btnApply.Enabled = value; }
}
public string TextOut
{
get {return txt.Text; }
}
private void applyButtonOnClick (object sender, EventArgs e)
{
if (ClickApply != null)
ClickApply(this, new EventArgs( ));
}
} // close for DialogDemo class
Example 6-6. DialogDemo class using an event in VB.NET
' Dialog box class
private class DialogDemo
inherits Form
dim btnApply as Button
dim txt as TextBox
public event ClickApply as EventHandler
public sub new ( )
myBase.New
Text = "Apply Dialog Demo"
FormBorderStyle = FormBorderStyle.FixedDialog
BackColor = System.Drawing.Color.Aquamarine
ControlBox = false
MaximizeBox = false
MinimizeBox = false
ShowInTaskbar = false
Size = new Size(400,200)
StartPosition = FormStartPosition.CenterScreen
' Create the OK button
dim btnOK as New Button
btnOK.Text = "OK"
btnOK.DialogResult = DialogResult.OK
btnOK.Location = new Point(50,50)
btnOK.TabIndex = 0
AddHandler btnOK.Click, AddressOf applyButtonOnClick
Controls.Add(btnOK)
' Create the Apply button
btnApply = new Button( )
btnApply.Text = "Apply"
btnApply.Location = new Point(150,50)
btnApply.TabIndex = 1
btnApply.Enabled = false
AddHandler btnApply.Click, AddressOf applyButtonOnClick
Controls.Add(btnApply)
' Create the Cancel button
dim btnCancel as new Button( )
btnCancel.Text = "Cancel"
btnCancel.DialogResult = DialogResult.Cancel
btnCancel.Location = new Point(250,50)
btnCancel.TabIndex = 2
Controls.Add(btnCancel)
' create input text box
txt = new TextBox( )
txt.Size = new Size(100,15)
txt.Location = new Point(150,15)
AddHandler txt.TextChanged, AddressOf TextBoxChanged
Controls.Add(txt)
end sub ' close DialogDemo constructor
private sub applyButtonOnClick(sender as Object, e as EventArgs)
RaiseEvent ClickApply(me, new EventArgs( ))
end sub
private sub TextBoxChanged(sender as Object, e as EventArgs)
dim txt as TextBox = CType(sender,TextBox)
dim dlg as DialogDemo = CType(txt.Parent,DialogDemo)
dlg.EnableapplyButton = true
end sub
public property EnableapplyButton as Boolean
get
return btnApply.Enabled
end get
set
btnApply.Enabled = value
end set
end property
public ReadOnly property TextOut as string
get
return txt.Text
end get
end property
end class ' close DialogDemo class
The first thing to note about the DialogDemo class is that it is nested inside the class of the parent form. This design implicitly makes the dialog box available to the Form1 class, but not to any other form. If you want to create a dialog box that will be accessible to different parent forms, then it needs public exposure, probably in a class by itself, or perhaps in a class that also contains other dialog box classes used by your application.
The next thing to note about the DialogDemo class is that it inherits from the Form class. The dialog box being created is just a form, like any other form. What makes it modal is the way it is called from the parent form. When the btnCreate button is clicked, the btnCreate_Click event handler method, shown in C# in Example 6-7 and in VB.NET in Example 6-8, is
Create the event handler for the Click event for the btnCreate button by going to the Design view and double-clicking on the button. Add the code highlighted in Example 6-7 (in C#) or in Example 6-8 (in VB.NET) to the code skeleton for the btnCreate Click
Example 6-7. btnCreate event handler using the ClickApply event in C#
private void btnCreate_Click(object sender, System.EventArgs e)
{
DialogDemo dlg = new DialogDemo( );
dlg.EnableapplyButton = false;
// Add the event handler
dlg.ClickApply += new EventHandler(DialogDemoOnApply);
// Show the dialog modally
dlg.ShowDialog( );
if (dlg.DialogResult = = DialogResult.OK)
{lblReturn.Text = dlg.TextOut;}
else
{lblReturn.Text = dlg.DialogResult.ToString( );}
}
Example 6-8. btnCreate event handler using the ClickApply event in VB.NET
Private Sub btnCreate_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnCreate.Click
dim dlg as new DialogDemo( )
dlg.EnableapplyButton = false
'
Add the event handler
AddHandler dlg.ClickApply, AddressOf DialogDemoOnApply
'
Show the dialog modally
dlg.ShowDialog( )
if dlg.DialogResult = DialogResult.OK then
lblReturn.Text = dlg.TextOut
else
lblReturn.Text = dlg.DialogResult.ToString( )
end if
End Sub
Before the ShowDialog( ) method can be called, the dialog box must be created. The first line of code in the btnCreate_Click method instantiates a new object of type DialogDemo. The instantiation of the dialog box looks like the following:
DialogDemo dlg = new DialogDemo( );
dim dlg as new DialogDemo( )
Once the dialog box is
The EnableapplyButton property is of type Boolean. It gets and sets the value of the Enabled property of the Apply button. If the Enabled property of a control is
false
, then the control is visible, but grayed out, and cannot receive focus. Thus, it cannot be clicked on or
After the dialog box returns from the modal display, the DialogResult property is
The DialogDemo class shown in C# in Example 6-5 and in VB.NET in Example 6-6 declares two member
private Button btnApply; private TextBox txt;
dim btnApply as Button dim txt as TextBox These are member variables, so they are visible to all the methods and properties in the DialogDemo class. The DialogDemo constructor sets various properties of the dialog box, including FormBorderStyle, BackColor, ControlBox, and MaximizeBox. The constructor then instantiates and specifies several controls on the dialog box: OK, Apply, Cancel, and a TextBox for accepting typed user input. Each control is added to the Controls collection of the dialog box. Both OK and Apply have the same event handler, ApplyButtonOnClick, added to the delegate for their Click event. This is because both buttons cause the text entered into the TextBox control to be displayed on the parent form.
The TextBox control raises the TextChanged event whenever the content of the TextBox is changed, either by adding or deleting
txt.TextChanged += new EventHandler(TextBoxChanged); and the TextBoxChanged method looks like:
private void TextBoxChanged(object sender, EventArgs e)
{
this.EnableapplyButton = true;
}
In VB.NET, the event handler is added to the delegate with this line of code:
AddHandler txt.TextChanged, AddressOf TextBoxChanged and the TextBoxChanged method looks like:
private sub TextBoxChanged(sender as Object, e as EventArgs) me.EnableapplyButton = true end sub An event called ClickApply was declared in the DialogDemo class (Example 6-5 in C#; Example 6-6 in VB.NET). This event will be handled by a method called DialogDemoOnApply, shown in Example 6-9 (in C#) or in Example 6-10 (in VB.NET). Enter the code for DialogDemoOnApply somewhere within the Form1 class, but not within the DialogDemo class. Example 6-9. DialogDemoOnApply method in C#
private void DialogDemoOnApply(object sender, System.EventArgs e)
{
DialogDemo dlg = (DialogDemo)sender;
lblReturn.Text = dlg.TextOut;
dlg.EnableapplyButton = false;
}
Example 6-10. DialogDemoOnApply method in VB.NET
private sub DialogDemoOnApply(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
dim dlg as DialogDemo = CType(sender, DialogDemo)
lblReturn.Text = dlg.TextOut
dlg.EnableapplyButton = false
end sub
The Apply button ultimately raises the ClickApply event when it is clicked. It does so through a
btnApply.Click += new EventHandler(applyButtonOnClick);
AddHandler btnApply.Click, AddressOf applyButtonOnClick The ApplyButtonOnClick method raises the ClickApply method. This method is reproduced here:
private void applyButtonOnClick (object sender, EventArgs e)
{
if (ClickApply != null)
ClickApply(this, new EventArgs( ));
}
private sub applyButtonOnClick(sender as Object, e as EventArgs) RaiseEvent ClickApply(me, new EventArgs( )) end sub
Since both the OK and Apply buttons perform the same task, with the only difference being that the dialog box
{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %} The parent form handles this ClickApply event by adding an event-handler method, DialogDemoOnApply, to the ClickApply delegate. This was done in the Click event handler for btnCreate, btnCreate_Click, which was listed in Example 6-7 (in C#) and Example 6-8 (in VB.NET). The method was added to the delegate with the following line of code:
dlg.ClickApply += new EventHandler(DialogDemoOnApply);
AddHandler dlg.ClickApply, AddressOf DialogDemoOnApply The DialogDemoOnApply method, which handles this event and is shown in Example 6-9 in C# and in Example 6-10 in VB.NET, gets an instance of the dialog box class that raised the event by casting the sender object as type DialogDemo. (Remember, even though sender is already of type DialogDemo, the compiler does not know this.) Once the reference to the DialogDemo dialog box is in hand, the value of the read-only TextOut property can be assigned to the label on the parent form and the EnableapplyButton property can be set to false , which disables the Apply button on the dialog box until the TextBox is modified again. Examine the DialogDemo class more closely. Notice there is no member variable of type Form1 (the parent Form class), and no direct coupling between the dialog box class and the parent class. There is, however, a declared public event delegate called ClickApply:
public event EventHandler ClickApply;
public event ClickApply as EventHandler This delegate is of type EventHandler, which specifies that the event-handler methods added to the delegate will take two arguments: an object (typically called sender) and an argument of type EventArgs (typically called e).
Looking back at the event handler method added to the ClickApply delegate, you can see that it does in fact
private void DialogDemoOnApply(object sender, System.EventArgs e)
private sub DialogDemoOnApply(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
|