# Modal Workflow

In a program, a modal workflow is a mode of operation in which a particular task or feature must be completed before the user can proceed to other tasks or features. This is typically implemented by displaying a modal window or dialog box that requires user interaction before continuing.

Modal workflows are often used when users must complete specific tasks or provide required information. For example, a modal workflow might prompt users to save work before closing a document, or enter login credentials before accessing restricted areas.

Modal workflows help guide users through specific steps or highlight important actions. However, if overused, they can disrupt workflow.

In web applications, supporting modal workflow means:

* Suspending server-side code execution
* Waiting for user input
* Resuming execution with received user information

While straightforward in desktop applications, this becomes challenging in web applications where code executes on the server and the UI runs asynchronously on different machines.

## Modal Workflow

The code and images below demonstrate how Wisej.NET handles modal code execution:

{% tabs %}
{% tab title="C#" %}

```csharp
void button1_Click(object sender, EventArgs e)
{
    if (MessageBox.Show("Are you sure?", buttons: MessageBoxButtons.YesNo) == DialogResult.Yes)
    {
          this.button1.BackColor = Color.Green;
          this.button1.Text = "You selected: Yes!";
    }
}
```

{% endtab %}

{% tab title="VB.NET" %}

```ruby
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
	If MessageBox.Show("Are you sure?", buttons:=MessageBoxButtons.YesNo) = DialogResult.Yes Then
		Me.Button1.BackColor = Color.Green
		Me.Button1.Text = "You selected: Yes!"
	End If
End Sub
```

{% endtab %}
{% endtabs %}

![Before clicking the button.](https://553579532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MF1D11gPs_az3xaKusw%2Fuploads%2Fgit-blob-cbbd75d7f7530701bb2b4565cd1f8f62069cb5f0%2Fimage.png?alt=media)

![After clicking the button.](https://553579532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MF1D11gPs_az3xaKusw%2Fuploads%2Fgit-blob-59d6e2fae2b4ee08f2d37e4c42091687a5d05f9a%2Fimage.png?alt=media)

The server code suspends, waiting for user choice. After clicking `Yes` or `No` on the client-side, the server code resumes exactly where it was suspended.

![After the user selected Yes.](https://553579532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MF1D11gPs_az3xaKusw%2Fuploads%2Fgit-blob-d8de5d5f604b5e8a73975cd167f6acf832477ea9%2Fimage.png?alt=media)

Wisej.NET supports:

* Nested modal states
* Custom `DialogResult` values
* Control references in modal dialogs
* User input data access

## Modal Dialogs

Modal workflow works for `MessageBox` and forms (dialog boxes) with any type of control, data binding, and code-behind. The example above, modified to use a modal dialog, looks like this:

{% tabs %}
{% tab title="C#" %}

```csharp
void button1_Click(object sender, EventArgs e)
{
  using (new dialog = new EnterCustomerAddress())
  {
    if (dialog.ShowDialog(this) == DialogResult.OK)
    {
        AlertBox.Show(dialog.textBoxAddress.Text + " " + dialog.textBoxState.Text);
    }
  }
}
```

{% endtab %}

{% tab title="VB.NET" %}

```ruby
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
	Using dialog As New EnterCustomerAddress()
		If dialog.ShowDialog(Me) = DialogResult.OK Then
			AlertBox.Show(dialog.textBoxAddress.Text + " " + dialog.textBoxState.Text)
		End If
	End Using
End Sub
```

{% endtab %}
{% endtabs %}

Regular modal dialogs or `MessageBox` controls suspend the current thread while waiting for user input. By default the system handles about 32,000 threads. While suspended, threads use no CPU time.

## Async Modal Dialogs

Wisej.NET fully supports the async/await programming pattern for modal dialogs.

Using the `await` keyword, a modal dialog can wait for closure without thread suspension. Simply use the "Async" version of the `ShowDialog` method.

{% hint style="info" %}
The async version of `MessageBox` is `MessageBox.ShowAsync(...)`.
{% endhint %}

{% tabs %}
{% tab title="C#" %}

```csharp
void async button1_Click(object sender, EventArgs e)
{
  using (new dialog = new EnterCustomerAddress())
  {
    if (await dialog.ShowDialogAsync(this) == DialogResult.OK)
    {
        AlertBox.Show(dialog.textBoxAddress.Text + " " + dialog.textBoxState.Text);
    }
  }
}
```

{% endtab %}

{% tab title="VB.NET" %}

```ruby
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
	Using dialog As New EnterCustomerAddress()
		If Await dialog.ShowDialogAsync(Me) = DialogResult.OK Then
			AlertBox.Show(dialog.textBoxAddress.Text + " " + dialog.textBoxState.Text)
		End If
	End Using
End Sub
```

{% endtab %}
{% endtabs %}

Asynchronous modal dialogs or `MessageBox` controls don't use any threads while waiting for user input.

## Custom Modal State

You can implement modal behavior and wait for user input without using modal dialogs or `MessageBox` controls. Wisej.NET provides `Application.DoModal(component)` for this purpose.

For example, the `PropertyGrid` uses `Application.DoModal()` to suspend code flow while waiting for dropdown selection box closure. Use `Application.EndModal(component, result)` to terminate the last modal state - modal states are stacked.

{% tabs %}
{% tab title="C#" %}

```csharp
// Open the combo box drop down list and wait
// for the user to select an item or close the combo box.
private void button1_Click(object sender, EventArgs e)
{
	this.comboBox1.DroppedDown = true;
	this.comboBox1.DropDownClosed += ComboBox1_DropDownClosed;
	this.comboBox1.SelectedIndexChanged += ComboBox1_SelectedIndexChanged;

	// wait for the user to either pick an item or close the drop down.
	var result = Application.DoModal(this.comboBox1);

	// code execution will resume here.
}

private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
	this.comboBox1.DropDownClosed -= ComboBox1_DropDownClosed;
	Application.EndModal(this.comboBox1, DialogResult.OK);
}

private void ComboBox1_DropDownClosed(object sender, EventArgs e)
{
	Application.EndModal(this.comboBox1, DialogResult.Cancel);
}
```

{% endtab %}

{% tab title="VB.NET" %}

```visual-basic
' Open the combo box drop down list and wait
' for the user to select an item or close the combo box.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

	Me.ComboBox1.DroppedDown = True
	AddHandler Me.ComboBox1.DropDownClosed, AddressOf ComboBox1_DropDownClosed
	AddHandler Me.ComboBox1.SelectedIndexChanged, AddressOf ComboBox1_SelectedIndexChanged

	' wait for the user to either pick an item or close the drop down.
	Dim result As DialogResult = Application.DoModal(Me.ComboBox1)

	' code execution will resume here.

End Sub

Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs)

	RemoveHandler Me.ComboBox1.DropDownClosed, AddressOf ComboBox1_DropDownClosed
	Application.EndModal(Me.ComboBox1, DialogResult.OK)

End Sub

Private Sub ComboBox1_DropDownClosed(sender As Object, e As EventArgs)

	Application.EndModal(Me.ComboBox1, DialogResult.Cancel)

End Sub
```

{% endtab %}
{% endtabs %}

The code above opens a dropdown and waits for user action. `DoModal` returns `DialogResult.Cancel` if closed without selection, or `DialogResult.OK` otherwise.

This provides powerful control over code execution and user action synchronization.

{% hint style="info" %}
`Application.DoModalAsync(component)` will be added in a future build.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.wisej.com/docs/concepts/modal-dialogs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
