Capture user input with two-way binding
Last updated
Last updated
© Ice Tea Group LLC, All Rights Reserved.
by 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:
We have a couple of labels, a TextBox
and a Button
.
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.
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.
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.
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.
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).
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:
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).
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.
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.
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
.
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:
I've added a DataGridView
(dataGridView1
) via the WYSIWYG editor then hooked that up to the BindingList
via the page's constructor.
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.
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?
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
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
We start by locating the currently selected row in the grid view:
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.
Once we have the details we can instantiate then show our editing window (theEditMovieDialog
dialog), giving it the movie details we just fetched from the database.
Here's the dialog itself:
EditMovieDialog
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).
With this we have a list of movies with a handy option for the user to edit each movie's title.
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.
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.