In my last post, I described how to use the Genome Web Application starter kit to rapidly create a web application that uses Genome. To prove that Genome is not just for web applications, I will now show how to create a windows forms application with Genome. There's no wizard that will create forms automatically (yet?), so there are a couple more manual steps. As you will see, however, it's not too difficult.
I open visual studio, and reuse the datadomain and mapping projects I created in the first post in this series. Then I add a new Windows Application project, call it WinForms and designate it as Start Project. I reference the datadomain and mapping projects, and the System.Configuration assembly. I also reference the TechTalk.Genome assembly, which is located in C:\Program Files\TechTalk\Genome 3.2 Professional Edition for .NET 2.0\Bin\TechTalk.Genome.dll on my pc. I rename the Form1 files to MainForm. I add an App.config file, and paste the connection string from the web project that I created in my last post. I then add a bindingsource to the form, and call it customersBindingSource. I configure the bindingsource to use the Genome.DataDomain.Customer class from the DataDomain assembly (1). I add a DataGridView control to the form, dock it to fill the form, and have it use the customer bindingsource. You can choose which columns you want to display in the grid; not all of them are that interesting to watch
So far, we used standard Windows Forms development techniques, but we still need to fill the datasource of our customer bindingsource. This is where it gets more interesting. We need a bit of plumbing code, but fortunately, we can use that most venerable of code reuse techniques: copy and paste. I Open up the directory where Genome is installed (C:\Program Files\TechTalk\Genome 3.2 Professional Edition for .NET 2.0 on my pc). I drill down to Samples -> CSharp -> QuickStart -> Step3-> WinFormsClient. I Copy the files ContextBoundForm.cs, ContextFactory.cs and Helper.cs to the directory of my WinForms project, and include them in the project. I open the files and change the namespaces to WinForms. In Helper.cs, I change the name of the _schemaAssembly field to "01ReverseEngineering.Mapping" (which is the name of the mapping assembly compiled by the mappings project from my first blog post in this series.). I change the name of the connection string to "MyRole" (or whatever you defined as the name of the connection string in your app.config file). Now I open MainForm.cs in code view and make the class inherit from ContextBoundForm.
This code won't compile yet. The reason being that there's a using directive TechTalk.Genome.Extensions.Windows.Forms in ContextFactory.cs. If you are familiar with the theory behind windows databinding, you will know that the IBindingList interface is essential when binding lists of data to a datagrid or a listbox. However, Genome's Set<T> (which is what is returned by any Genome query) does not implement that interface. The Genome team provided a SetBindingList<T>, which is a wrapper around Set<T> that implements IBindingList. You can find the code for this class in C:\Program Files\TechTalk\Genome 3.2 Professional Edition for .NET 2.0\Extensions\Windows.Forms\SetBindingList.cs. I add this file to the WinForms project (you can add it either as a copy or as a link). I compile to make sure that I have copied all code I need.
What is all this plumbing code about? One of the central concepts in Genome is the Context. A idea of a Context in Genome is comparable to a connection to a database. There can be many connections to the same database, but you need at least one connection in order to do something usefull on your database. The same is true for a Context. The Genome equivalent of a database is called DataDomain, by the way. ContextBoundForm inherits from System.Windows.Forms.Form and adds a propery and a couple of methods for using a Context. ContextFactory does exactly what its name suggests.
Now at last we can populate the custerm binding source. I open MainForm.cs in design view, and double-click on the Form's title bar to create a handler for the load event. Thanks to all our plumbing code, I only need to write customersBindingSource.DataSource = new SetBindingList<Customer>(Helper.DB.Extent<Customer>(Context)); - after adding using directives for Genome.DataDomain and TechTalk.Genome.Extensions.Windows.Forms, that is. I hit F5 to debug and run the application. If all goes well, the main form loads and you will see the list of customers in the data grid. In my case, not all went well at first and I had to make sure that my windows user account had appropriate permissions on the Northwind database. The result looks something like this:
That's it for today. This post turned out to be way longer than I anticipated, so I will save up the Orders and OrderDetails part and the editing part for the next post.
(1): If you have never worked with bindingsources in a windows forms application (and even if you have), I can highly recommend Brian Noyes's book Data Binding with Windows Forms 2.0 - Programming Smart Client Data Applications with .NET: it's full of information about working with data binding in Windows Forms, and is an enjoyable read. If you are interested in the inner workings of data binding, be sure to check out chapter 7, Understanding Data-Binding Interfaces.
Posted by Dirk
Technorati Tags: object relational, getting started