# Capture user input with two-way binding

*by* [*Jon Hilton*](https://www.learnwisej.net/authors/jon-hilton)

Sooner or later you're going to want to enable data input for your web app, so users can add, edit, and delete data.

Whether it's to update their profile, complete a short form, or edit rows in a table, inputting data is a major part of the story for many Line Of Business web applications.

So how does WiseJ handle this requirement…

There are a few options, here are the most common (and useful).

Perhaps the simplest is to programmatically retrieve (or set) the value of an input field at the point you need it.

Here's an example:

<figure><img src="https://3188166459-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYZg1RIEjJ5H42ECDnFfU%2Fuploads%2F8Mj9hKw3oNQKzus3tHpl%2Fimage.png?alt=media&#x26;token=b544771e-958c-4f5f-8081-c2be3fa4327d" alt=""><figcaption></figcaption></figure>

We have a couple of labels, a `TextBox` and a `Button`.&#x20;

We can wire up an event handler for the button click event, grab the value of the text input, and use it to set a value for our label.

```csharp
public partial class SimpleInput : Wisej.Web.UserControl
{
    ...

    private void button2_Click(object sender, EventArgs e)
    {
        lblMesage.Text = "Hello " + txtName.Text + "!";
    }
}
```

This is nice and simple for quickly taking user input and doing something with it but sometimes you'll want a slightly more 'automatic' approach, where you can keep track of values entered by a user.

For this you can use **Data Binding**.

### Simple Binding

You can take a standard input control (like a text box) and bind it to a property on an object.

When the user enters a new value, the object is updated.

```csharp
public partial class SimpleInput : UserControl
{
    private Person person = new Person();

    public SimpleInput()
    {
        InitializeComponent();
        txtName.DataBindings.Add("Text", person, nameof(person.Name));           
    }

    private void button2_Click(object sender, EventArgs e)
    {
        lblMesage.Text = "Hello " + person.Name + "!";
    }
}

public class Person
{
    public string Name { get; set; }
}
```

Now the text property of `txtName` is effectively linked to the `Name` property on `person` (an instance of the `Person` class).

With this we can retrieve the entered value at any time via `person.Name`, as we do in the button click event handler.

```csharp
lblMesage.Text = "Hello " + person.Name + "!"; 
```

But what if we want to keep the UI in sync with changes happening in code.

For example, we might want to wire up a **Reset** button that clears the person's name when clicked, and therefore clears the textbox.

With the binding in place you might expect you could just reset the value of `person.Name` and the text input would show the new value (an empty string).

```csharp
private void btnReset_Click(object sender, EventArgs e)
{
    person.Name = string.Empty;
}
```

However, as it stands the UI textbox value won't be updated (it will show the previously entered value).

We can solve this by making the underlying `Person` class implement `INotifyPropertyChanged`.

`INotifyPropertyChanged` is a handy mechanism we can use to tell .NET when something has changed.

To implement `INotifyPropertyChanged` we need to define a `PropertyChanged` event:

```csharp
public class Person : INotifyPropertyChanged
{
    public string Name { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
}
```

With this in place it's then a question of invoking the `PropertyChanged` event at the right time (when the `Name` property's value is updated).

```csharp
public class Person : INotifyPropertyChanged
{
    private string _name;

    public string Name
    {
        get => _name;
        set
        {
            if (_name != value)
            {
                _name = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
```

Now every time we set `Person.Name` to a new value, `PropertyChanged` will be invoked, and our binding will ensure `txtName` is updated to reflect the new value.

<figure><img src="https://3188166459-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYZg1RIEjJ5H42ECDnFfU%2Fuploads%2FgZojPr4Rm33GXuZtk0Vl%2Ftwo-way-binding.gif?alt=media&#x26;token=a33466ec-7565-4e80-89fa-a96be61b6018" alt=""><figcaption></figcaption></figure>

But what if we want to go a step further and enable editing of multiple records via something like a data grid? For this we may need to turn to a more advanced form of databinding.

### Complex Binding

Say, for example, you want to present a number of records in a grid (as we saw when we explored showing data via WiseJ) and enable editing of those records.

One option here is to use a `BindingList`.&#x20;

This is particularly handy when you have any kind of list of objects and want to hook them up to a data control (such as a `DataGridView`).

For example, we can create a Binding List of `Person` objects:

```csharp
public partial class ComplexInput : Wisej.Web.UserControl
{
    BindingList<Person> people = new BindingList<Person>();

    public ComplexInput()
    {
        InitializeComponent();        

        dataGridView1.AllowUserToAddRows = true;
        dataGridView1.AllowUserToDeleteRows = true;
        dataGridView1.DataSource = people;            
    }

}
```

I've added a `DataGridView` (`dataGridView1`) via the WYSIWYG editor then hooked that up to the `BindingList` via the page's constructor.&#x20;

With this we get a list of people's names, and can add, edit and delete records safe in the knowledge that the underlying list will be updated accordingly.

<figure><img src="https://3188166459-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYZg1RIEjJ5H42ECDnFfU%2Fuploads%2FV3lU89BmoVROblezue4m%2Fcomplex-input.gif?alt=media&#x26;token=c9b32340-d9cb-44f0-92ed-9b6eb664eab5" alt=""><figcaption></figcaption></figure>

This is all well and good for in memory lists, but what if we want to persist changes to a database and perhaps provide our own custom UI for editing?

### Putting it all together with a real database

Let's look at a concrete example where we'll use a combination of the `DataGridView` to show a list of movies, and a little bit of **Simple Binding** to present a custom edit dialog for editing a movie's title.

In the previous article we used Dapper to fetch a list of movies from a database and present it to the user via a `DataGridView`.

**DapperExample.cs**

```csharp
private async void LoadData()
{
    using (var connection = new SQLiteConnection(DBConfig.ConnectionString))
    {
        this.moviesBindingSource.DataSource = await connection
            .QueryAsync<MovieSummary>("SELECT Title, Summary FROM Movie");

        this.dgMovies.DataSource = moviesBindingSource;              
    }
} 
```

Now let's suppose we want to enable users to edit the title of any of the movies in this list.

In this case we want to show a custom dialog window which can be used to edit the title.

Here's the flow we're aiming for:

* User double-clicks the row for the movie they want to edit
* A dialog window opens with a form containing a single text input for the movie's title
* The user makes their changes and clicks Save (or OK)
* The new values are used to update the relevant record in the database

We can use the grid view's `DoubleClick` event to wire up the `DoubleClick` event:

**DapperExample.cs**

```csharp
+...

private async void dgMovies_CellDoubleClick(object sender, Wisej.Web.DataGridViewCellEventArgs e)
{
    if(e.RowIndex >= 0)
    {
        using (var connection = new SQLiteConnection(DBConfig.ConnectionString))
        {
            // figure out which item was selected in the grid
            MovieSummary selectedItem = (MovieSummary)dgMovies.Rows[e.RowIndex].DataBoundItem;
                        
            var selectQuery = "SELECT * FROM Movie where Id = @id";
            
            // fetch the details for the specific movie
            var details = await connection.QuerySingleOrDefaultAsync<MovieDetails>(
                selectQuery, new { selectedItem.Id });

            // create a new instance of the dialog window (and pass along the movie details via its constructor)
            using (EditMovieDialog editDialog = new EditMovieDialog(details))
            {
                // show the dialog
                var result = editDialog.ShowDialog();
                
                // run this logic when the dialog result is 'OK'
                if(result == DialogResult.OK)
                {
                  // save changes
                  // refetch data
                }
            }
        }
       
    }
}
```

We start by locating the currently selected row in the grid view:

```csharp
MovieSummary selectedItem 
    = (MovieSummary)dgMovies.Rows[e.RowIndex].DataBoundItem;                
```

With this we know the `Id` of the movie we want to edit.

We can then go ahead and use Dapper to fetch the relevant details.

```csharp
var selectQuery = "SELECT * FROM Movie where Id = @id";
 
 // fetch the details for the specific movie
 var details = await connection.QuerySingleOrDefaultAsync<MovieDetails>(
     selectQuery, new { selectedItem.Id });
```

Once we have the details we can instantiate then show our editing window (the`EditMovieDialog`  dialog), giving it the movie details we just fetched from the database.

```csharp
using (EditMovieDialog editDialog = new EditMovieDialog(details))
{
    // show the dialog
    var result = editDialog.ShowDialog();
    
    ...
}
```

Here's the dialog itself:

**EditMovieDialog**

```csharp
public partial class EditMovieDialog : Form
{
    public Data.MovieDetails UpdatedDetails { get; set; }

    public EditMovieDialog(Data.MovieDetails details)
    {
        InitializeComponent();

        this.UpdatedDetails = details;
        txtTitle.DataBindings.Add("Text", UpdatedDetails, nameof(UpdatedDetails.Title));           
    }

    private void btnSave_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.OK;
        this.Close();
    }
}
```

We use bindings (as we saw earlier) to ensure the value entered into the `txtTitle` text input is reflected in the underlying model (`UpdatedDetails`).

When the user clicks the **OK button** the dialog result is set to `OK` and the dialog is closed.

Back in our main page we can retrieve the updated details, make a call to update the DB (and then re-fetch the data so we can show it in our grid view).

```csharp
...

using (EditMovieDialog editDialog = new EditMovieDialog(details))
{
    var result = editDialog.ShowDialog();
    if(result == DialogResult.OK)
    {
        var updatedRecord = editDialog.UpdatedDetails;

        var dbSaveResult = connection
            .Execute("UPDATE Movie set Title = @title where Id = @id", 
            new { editDialog.UpdatedDetails .Title, selectedItem.Id});

        LoadData();
    }
}
```

With this we have a list of movies with a handy option for the user to edit each movie's title.

<figure><img src="https://3188166459-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYZg1RIEjJ5H42ECDnFfU%2Fuploads%2FeAUGpBnBWh0BCZWzFE61%2Fimage.png?alt=media&#x26;token=784f0b84-f773-46e5-9b10-b5cad8a5276c" alt=""><figcaption></figcaption></figure>

When the user clicks **Save** the dialog is closed (with an OK dialog result) and the code in the main **DapperExample** page calls the database to update the selected movie's title.

### In Summary

There are numerous methods for accepting user input via WiseJ, here we've explored some of the key underlying mechanisms.

You can interact with input controls (like a text box) directly or use binding to ensure you always have access to their current values.

`INotifyPropertyChanged` is useful to ensure your UI stays in sync with your models.

Finally, complex binding is useful when you want to interact with records via built-in data presentation controls like a grid view.
