DataView for Objects: Final Cut
Posted on November 19, 2006
Note: You can download the complete implementation here.
In my last post I described the implementation of IBindingListView interface in ObjectListView, my implementation of a view for collections of arbitrary objects. This was the last interface needed to support binding to controls such as the DataGridView.
In this post, I’ll show some sample code that demonstrates the use of ObjectListView.
The Demo
I’m going to display data from the Microsoft sample Northwind database in a ComboBox and a DataGridView, showing how to filter and sort with ObjectListView. Here’s the main window:
After installing the Northwind database (available here), alter the configuration file Demo.exe.config to reflect your computer name (in place of “DADBOX”). Alternatively, you can modify the connection string in the text box of the demo program main window.
Run demo.exe, set the connection string if needed, and press the Get Data button. This causes two lists to be populated from the database. For the demo, I’ve created two classes, Customer and Order, which do nothing but hold the data from a row in the corresponding database table. The two lists I’m populating are a List<Customer> and List<Order>. Then, I create two instances of ObjectListView, binding one to the customers list, and one to the orders list:
private void buttonGetData_Click(object sender, EventArgs e) { Database db = new Database(); db.ConnectionString = this.textBoxConnectionString.Text; viewCompanies = new ObjectListView(db.GetCustomers()); viewOrders = new ObjectListView(db.GetOrders()); this.comboBoxCustomers.DataSource = viewCompanies; this.comboBoxCustomers.DisplayMember = "Company"; this.comboBoxCustomers.ValueMember = "Id"; this.dataGridView.AutoGenerateColumns = false; this.dataGridView.DataSource = viewOrders; this.textBoxFilter.Text = ""; this.textBoxFilter.Enabled = true; }
Finally, I set the data source of the company ComboBox to the customers ObjectListView, specifying that the Company property of each Customer will be displayed, and that the Id property will be returned from ComboBox.SelectedValue. The data source of the grid is set to the orders ObjectListView. Each grid column is bound through it’s DataPropertyName property to a different property of Order. The column binding code is in designer-generated code.
Now the ComboBox contains a list of all of the customers. When we select a customer, the orders ObjectListView is filtered to present only the orders for the selected customer:
private void comboBoxCustomers_SelectedValueChanged(object sender, EventArgs e) { if (this.comboBoxCustomers.SelectedValue == null) this.viewOrders.Filter = "CustomerId=null"; else this.viewOrders.Filter = "CustomerId='" + this.comboBoxCustomers.SelectedValue.ToString() + "'"; }
Note the usage of CustomerId=null above, to indicate that the CustomerId property of Order should be compared to null when no customer is selected.
Once the grid is populated with orders, you can click on the column headers to sort the orders. This is done behind the scenes by DataGridView, which delegates to the IBindingList.ApplySort implementation of ObjectListView.
You can also filter the companies displayed in the ComboBox by entering text in the filter TextBox. As the text is changed, the customers ObjectListView filter is updated:
private void textBoxFilter_TextChanged(object sender, EventArgs e) { this.viewCompanies.Filter = "Company=" + this.textBoxFilter.Text + "*"; }
That’s all there is to it! We’ve bound lists of arbitrary objects to both a DataGridView and a ComboBox, sorting and filtering our views of the lists without changing the lists themselves, in just a few lines of code.
What’s ahead
There’s a few things I know want to add to ObjectListView, and I’d like your feedback on other enhancements that you’d like. Please email me and let me know how you’re using ObjectListView and what you think should be added or changed. In the meantime, I plan on adding:
- More complex filter expressions (!=, <, >, LIKE, NOT, etc).
- Support for code-based filter predicates (provide a callback method rather than a filter string expression).
- BeginUpdate() and EndUpdate() methods to suppress ListChanged events while doing a large number of list insertions/deletions.
- User-provided comparer for custom sorting.
I’ve enjoyed building ObjectListView – I hope you find it useful!
Got something to say?