Free!  FoxPro to WPF screen converter
   Almost free!  One day of FREE VFP to WPF evaluation of your FoxPro app ONSITE
   Free!  Read the foreword to Les' new book (available here)...
Skip Navigation Links

Introduction to StrataFrame ListViews

ListViews are a good way to display lists; StrataFrame makes them better

Les Pinter

Login or register to download source code

Coding time: 10 minutes.

 Jump to:   .NET ListViews   The StrataFrame approach   Conclusion 



Users like to see their data. ListBoxes, ListViews and DataGrids are three ways that you have to display lists of records, and each has its strengths and weaknesses. ListBoxes are simple, but lack power. Grids have everything, but can be slow when data volume is high, and attempts to use grids as data entry mechanisms cause more interface design problems that just about anything.

That leaves the ListView. The native .NET control isn't bad. but as usual, StrataFrame data-aware technology can improve on it. StrataFrame can create business objects, and business objects have properties, events and methods that a smart listview could definitely take advantage of. StrataFrame's ListView does.

Populating a .NET ListView

Create a WinForms application, select form1, and add a .NET listview. Then, open the listview and look for the place to attach a datasource. There isn't one. That may not surprise you, but as a guy who's been doing database apps for, well, a long time, it sure as heck surprises me. What did they think it was for? Why should you have to write code to do the only thing that the control is designed to do? My only conclusion is that Microsoft just doesn't get data.

Happily, StrataFrame does. For today's example you'll load a StrataFrame ListView with the last name, phone number and email columns from the StrataFrameSample Customers table (the column names are actually cust_LastName, cust_PhoneDay and phone_Email) - and you'll do it with one line of code. But first, you'll need some data.

Retrieving data .NET style

If you know what to write, you can just start coding. Add the correct using statement, add a dataadapter, then a dataset, load the dataset... perfectly obvious, unless you've never done it before, in which case you'll spend hours trying to figure it out. Thank God for the Internet, without which .NET would be nearly impossible to learn.

However, there are some code-generation tools built into the IDE. If you go to the IDE menu and select Data, Add Data New Source. Select DataBase as the DataSourceType (Fig. 1):

Accept the default connection string name (Fig. 2)

From the available StrataFrameSample tables, expand the Customers table entry and select the three fields cust_LastName, cust_PhoneDay and cust_Email (Fig. 3)

From the little downward-pointing arrow beside the Customers tablename (Fig. 4), select DataGridView (Fig. 5):

Then, drag and drop the word Customers onto the form; a DataGridView and a BindingNavigator will be added to the form (Fig. 6).

The reason I dragged the datasource to the form designer surface was because doing so creates the mechanisms that I need to load the listview:

  1. The dataset, strataFrameSampledataSet; and
  2. the customersTableAdapter, including its connection string (which is stored in config.sys)

Select and delete the BindingNavigator and DataGridView, and you'll have what you need to populate the ListView (Fig. 7).

Loading the ListView

There is one step that all ListViews require no matter how they get their data: You have to define the Columns collection. Right-click on the little button to the right of Columns in the Properties Sheet and you'll see the Property Editor shown in Fig. 8:

Add three columns, naming them colName, colPhone and colEmail. Make the widths 100 each, and change the Text properties to Name, Phone and Email respectively. Then, close the Columns Property Editor.

The next step is perhaps the most important one: Change the ListView's View property to Details. Why it doesn't default to Details is beyond me. You can spend hours wondering why your columns of data don't appear (Fig. 9):

<rant>Of course, as I've pointed out in article 414 on my website, you should start every project by subclassing all of the WinForms controls, and as long as you're under the hood, change the listview's default View to Detail.</rant>

You can now write the code to populate the listview that you dropped on the form at the very beginning of this article. (Note that the first line of code was generated when we dropped the data source on the form.) (Listing 1):

Press F5 to run the form and verify that it works.

It might just be me, but I think this is too much work to load a three-column listview. Let's see what StrataFrame can do to improve the situation.

The StrataFrame Approach

The StrataFrame ListView can be populated with as little as a single line of code. Instead of requiring code, the details of where to get the data for the columns moves to a PopulationDataSource property editor. You fill in the blanks, and it does the rest.

As always, you'll start with a StrataFrame Windows Application project. You'll have to choose the language, but in this article you'll include the code for both C# and VB. The starting project appears in Fig. 10, below:

We'll flesh out the form shortly. But first, the data.

Adding the business object

StrataFrame uses Business Objects (table classes) that it generates directly from your datasource. We'll use the Customers table from the StrataFrameSample database that installs with StrataFrame. Right-click on your project and select Add, New Item, then pick SF Business Object from the available items. Be sure to change the name to CustomersBO before you click Add (Fig. 4)

However, at this point it doesn't really contain any code that is specific to your table; it's just an empty class. To add the table-specific code, you use the StrataFrame Business Object Mapper (the first menuitem in the StrataFrame menu pad). The BOM is a utility that reads the structure of the data source, and then generates (among other things) one public property for each column in the underlying table in the selected business object class. This is what allows you to use the notation Customers.Address1, which has no intrinsic meaning in .NET unless you have an object named Customers with a public property named Address1.

Next, you need to flesh out the CustomersBO class. Click on Business Object Mapper from the StrataFrame menu pad in the IDE menu. You'll see the treeview in Fig. 12. The little red "x" over the Project name and the business object below it indicate that they're not yet "configured" (i.e. associated with a database and table).

To do this, select the project name from the Available Projects tree and click on the Configure Project link, which becomes enabled when you select the project name.

You don't yet have one, so in the Choose Project dialog, click the New Button. Then, from the Project Properties screen that appears, fill in a project name and description. Leave the Database Deployment Toolkit radiobutton selection in the Default Structure Settings group as it is; this is an external file used in the IDE where StrataFrame stores project information. (You can also store it in a database, but you generally won't do so.) Be sure to select the new project (on the Choose Project dialog page) after you create it.

You could, of course, drag and drop a SQLDataAdapter and a DataSet from the toolbox and configure them. But to do that, you'd need to know that that was what you needed. If you've been developing for years, you might have forgotten how incredibly difficult it is to figure out what you need to do even the simplest task in ,NET. I don't dislike .NET for deficiencies in its design; I dislike how unbelievably hard it is to learn. Basically, if you don't have a functioning example of what you need, you're not going to figure it out. And even then, simply seeing something that works doesn't explain why it works. That's why I'm writing these articles.

Once you've configured the project, highlight CustomersBO and click on the Configure Business Object link (Fig. 14) to produce the screen shown in Fig. 15:

Select the SQL Server radio button and click the Select Source button: You'll be able to expand the StrataFrameSample database node and pick the Customers table (Fig. 16).

The result is a display of the columns in the table. These will be exposed as public properties in the business object class code that will be generated by the Business Object Mapper (Fig. 17):

When you close the BO generation dialog screen, you'll see that the little red "x"s have disappeared. There are other useful things that can be done in the BOM, but for the moment you don't need to do anything else. Select Rebuild All, and close the BOM dialog.

You're done creating business objects. Unless you change the structure of one of your tables, you probably won't open the BOM again.

Data Retrieval Methods

Ever since I can remember, it's been considered best practices to relegate SQL statements to your business objects and thereby keep SQL out of your presentation code ("separating the interface from the implementation"). The way you do that in StrataFrame is by putting them in the business object.

You might think that a Business Object knows how to return data; it doesn't. You usually have to write a line or two of code. For the CustomerBO object, you'll want to return, say, 100 records (The StrataFrameSample database Customers table has over 19,000 customers in it, and you don't want to load them all into a ListView). To do that, you'll write a method that in turn calls one of the public methods found in all SF business objects - FillDataTable. It takes a single parameter: A SQL SELECT statement. It doesn't need to return the records; FillDataTable stores them in the business object.

To add our FillTop100 method for CustomerBO, double-click on CustomersBO in the Solution Explorer and select Click here to switch to code view. Expand the Data Retrieval Methods region of CustomersBO and add this (Listing 2):

Rebuild the project, and you're ready to populate the ListView.

Populating the ListView

Before you dive into the details of the forms, let's talk for a minute about how StrataFrame ListViews are populated. A SF ListView has its own internal datatable. You can pass in a datatable, but you can also use any number of other ways to load it. In parent-child scenarios, you can load records into the child business object just before the child form is launched using a ChildFormDialog (See Article 411). The ListView of the child form can then simply copy the records you just stored in the child business object into the listview's internal table. Since the ChildFormDialog's BusinessObjectTranslation copies the records from the calling form's business object to the child form business object, the child table data is isolated, and saving or abandoning changes is simplified.

There are two steps involved in populating a ListView in StrataFrame:

  1. Declaring the Columns collection; and
  2. Defining the PopulationDataSource

Rather than requiring yuo to write code to load the listview, the SFListiew provides you with a property editor that collects and stores everything it needs to know, and then uses it at instantiation time to do all of the work for you. The property that launches this peroperty editor is called PopulationDataSource.

The Columns collection is very straightforward: How many columns, how wide, and with what headings. You can set up even a complex ListView's columns in a minute or two. But that's not where the work takes place.

Clicking on the PopulationDataSource property of a SFListView displays a fairly complicated property editor (Fig. 18):

In this property editor, you have to select four things:

  1. Which business object to use;
  2. Which data retrieval method to execute; this will often be one that you wrote in your business object - (FillTop100). However, it could be one of several others built into the business object. ListViews are not editable, so if you're going to return to the form multiple times, you may not want to go back to the server each time you reload the listview. For example, CopyDataFrom assumes that the business object has already been loaded once (in the form's constructor), so it just grabs a copy whenever it needs it. CopyDataFrom() requires 2 parameters, which you specify in the ListPopulating event. (I'll show you how to use it in a forthcoming article.)
  3. Which display fields to use; in the process of adding them, they are assigned numbers; these numbers are what you have to refer to in the next step; and
  4. The columns to display; the only oddity is that, instead of column names, you use the field numbers from the left side of the dialog to specify which fields to use in which columns.

You'll next add four Fields: FirstName, LastName, DayPhone and Email. This is just a field list for the Columns list at the right, so don't try to get creative just yet. Just add the column names and note their sequence numbers.

On the right side of the dialog, you'll define the content for the three Columns that you added in Fig. 8. The sequence numbers assigned under Fields are surrogates for the column names. It looks a little clumsy (and it is), but it allows you to use format strings to doll up the data you get from the table - like displaying LastName, comma, FirstName in the Name column.

All three columns get their data from the fields at the left side of the dialog. {1}, {0} is (field 2, comma, field 1). Just make sure that the column's data matches the column headings.

But wait: Where does the FillTop100() method run? the answer is in the Properties Sheet for the ListView, just above the PopulationDataSource property. Notice that the property just above it is called the PopulateOnFormLoad property. The two choices are Manual and FormLoad. By selecting FormLoad, we've told the listview to execute the FillTop100() method in the form's Load event. You don't have to write any code in the Load method. It's all taken care of.

Press F5 to run the application. As with any StrataFrame app, the first time you run it, you have to confirm which server and database to use (After this initial setup, you won't see this dialog again.) (Fig. 19):

Finally, there's your data (Fig. 20):

Wrapping up

We've managed to reduce the code necessary to populate a listview to one line of code - the FillTop100 method we wrote in the CustomersBO business object - and that was mostly a SQL SELECT statement.

There are more things that you can do with StrataFrame ListViews; You can conditionally insert graphics images in a column; you can calculate a value based on the contents of an existing column. These variations use the RowPopulating event, and we'll show you how to use it in a forthcoming article.


Listviews are a common feature in interface design. StrataFrame makes building ListViews a pleasure, and isn't that what a framework should do?

See 'ya.


Copyright(C) Pinter Consulting, 2012Tel: +1 (650) 464-6924
Automated conversion between C# and VB by Visible C#/Visible VB from Tangible Software Solutions