CodeSmith Community
Your Code. Your Way. Faster!

Tutorial for building a windows forms application

Latest post 11-01-2007 8:16 PM by TFOGARTY. 12 replies.
  • 08-08-2007 12:47 AM

    • fweeee
    • Top 25 Contributor
    • Joined on 08-08-2007
    • Posts 187
    • Points 4,608

    Tutorial for building a windows forms application

    Hi,

    I'm trying to build a windows forms database application, and it has been recommended to me to use nettiers/codesmith to assist me. Now I have downloaded the software, and generated the code from my database (its a very simple database at this stage), but I'm having trouble moving on from here.

    Although I was told that nettiers/codesmith would work fine for windows forms applications, I'm having a lot of difficulty finding information on how to do it (most of the website information is aimed at website writing).

    If someone can point me to a tutorial on how to do this (windows form application with nettier), it would be much appreciated.

    Thanks.
     

    • Post Points: 65
  • 08-11-2007 4:54 AM In reply to

    • JRich
    • Top 150 Contributor
    • Joined on 04-24-2007
    • Posts 30
    • Points 785

    Re: Tutorial for building a windows forms application

    I am doing a large windows app with NetTiers and here are a couple of guidelines I use:

    1. Separate your DataLayer solution from your app.

    There is a temptation to generate the NetTiers solution and then start extending with your functionality. I prefer to keep the datalayer solution separate. I generate the datalayer solution, compile it, then reference it where required in my app's solution. That way (at least I believe) as you make adjustments to your database and have to change your datalayer, there will be minimal direct impact on your app.

    2. Take advantage of the Windows forms edit controls created by NetTiers (Set the GenerateWinLibrary to TRUE)

    I have not had much use for the nettiers DataGridView controls. But this is another topic. For now, my recomendation is to stick with the Edit controls.

    This requires a little up front work, but is worth it. The winforms controls created by nettiers are in effect "visual" representations of the entity upon which they are based. Generally fields are represented with TextBoxes, but date fields produce DateTime pickers and foreign key's produce combo boxes. Each combo box (foreign key) will expose a "list" property for that control which corresponds to the TList object based on the entity represented by the foreign key. So if you had a Customer entity that included a foreign key from a Customer Type table, the netiers Customer Edit control would expose the Customer Type field as a combo box and provide a property to which you can bind the TList object for the Customer Types.

    An initial annoyance is that the controls are created using the column name as the label text on the control. So your CompanyName control's label will be...CompanyName. But this can be overcome with a one time effort.

    I go into my database and for EACH column in every table, modify its extended properties. If you haven't accessed the extended properties, look up how to do it. Its pretty straight forward. My modification is to add an extended property to each field and set that properties value to a string I want to appear. So for the CompanyName column, I would put Company Name into the extended property.

    You have to make a minor change to the Windows.Forms codesmith template so that at the point where it is creating the labels, it uses the extended property value rather than the column name. I will share my modification with you if you need it.

    Finally you should not try to use the NetTiers custom controls directly as they are created. The problem is all of their properties are "protected" thus are not available to you at design time in your project. However, there is an easy solution to this. Add a Custom Controls project to your apps solution. Then for each NetTiers edit control you need to use, create a user control class in your Custom Controls project and change its inheritence from Controls to your NetTiers custom control.  This inheritance exposes all of those protected properties you need. Again, if you haven't done this before, I can send you a write up on how to do it.

    The cool thing is that each control you add to your Custom Control project will automatically appear in your tool box. Just drag it to your form and you are good to go.

    3. Have fun..

    Joe Rich

    Rich Solutions

    Filed under: ,
    • Post Points: 95
  • 08-12-2007 9:55 AM In reply to

    • Tihomir
    • Top 500 Contributor
    • Joined on 12-04-2005
    • Posts 15
    • Points 275

    Re: Tutorial for building a windows forms application

    Almost complete tutorial, but what about datagridview control ? Namely, DataGridView is not fully design-time customizable. When I've tried to add new column, I've got an error ("Column cannot be added because its CellType property is null "). Most of the other properties I can customize (I'm using Nettiers 2.2 rev 607.) . Did you developed CAB applications Joe ? I Have an idea to merge CAB templates with existing WinForms library templates to create SmartParts which I can customize in design time. What do you think about that ? Is it worth to try ?
    • Post Points: 10
  • 10-26-2007 11:24 AM In reply to

    • Polar
    • Top 100 Contributor
    • Joined on 09-04-2007
    • Posts 51
    • Points 935

    Re: Tutorial for building a windows forms application

    JRich, can you tell me how to edit the template to get the label text from extented properties.

    Thanks

    • Post Points: 5
  • 10-26-2007 2:24 PM In reply to

    • mathisr
    • Top 150 Contributor
    • Joined on 03-05-2006
    • Posts 32
    • Points 490

    Re: Tutorial for building a windows forms application

    NetTiers is great! There are a few kinks to work out, especially since I'm a newby, but after getting the config file set, reviewing some samples and working with it I'll never go back to CSLA.

    Yup, there are some windows forms controls created by the template manager but I've not had the chance to work with them. I use Infragistics and I have little time to build a base control for each Infragistics control, would have to code and test each class... Maybe next  year. However for now I have developeed a few strategies that help solve some problems that make life easier.

    The thing is to generate the NetTiers classes. This will take a little time at first but after reading the limited help at NetTiers.Org you should be an old hand after a few days. Basically you need to setup some template parameters i.e. your Source Database, Output directory and Root Name. There are a few more setting that are beneficial to know as well i.e. IncludeDatabaseFeatures, BusinessLogicLayerNameSpace, DataAccessLayerNameSpace, ParseDbColDefaultVal and IsolationLevel. There are others but I find these are the most important for my apps.

    Of course you should know what version of the NetTiers template your using as well. From the download page you'll find a "Nightly Builds" Section. This is where the newest builds of the template can be found.  For awhile I feared this page because it had cause my applications to break. LOL But since build 2.2 I've had not problems with latests builds.

    You should be aware that the builds require the Microsoft Enterprise library. You might want to research this technology and get a better handle on the features you can utelize.

    When building from the template you will get a set of directories and classes that provide all your data access, some really nice functionality. You will also get a report webpage popup that describes what classes were generated as well as how to impliment the config file.

    I always create a directory under the project's root directory for holding the NetTiers generated classes and set the Output directory there.

    You also have options, in the template, to build a ComponentLayerNameSpace. I tried to use this feature at first but ran into problems because I'm always making changes to my database as I design and code. I'm a single developer I don't get lots of chances to architect, design and code my application. Just create basic archeticture and run.... And sometimes I have to make patches to the NetTiers templates to get what I want, this means I have to physically delete some of the classes each time I rebuild from the template. I found it easier to just delete the complete directory and regenerate all the files again. So When I tried using the ComponentLayerNameSpace I would have to individually copy files modified from Visual Studio, became difficult considering I sometimes regenerate NetTiers every couple hours in a single day. My bad!

    However, I have in essance create a simple version of the ComponentLayerName Space as you should consider doing to help limit headaches down the road.

    Most apps I design are multiuser and require sycronizing the database at all times with all user views on each client workstation. This is a reall hassle believe me. But the Component Layer has simplified it some. For example; Each table has a static class in the application and a asscociated propery for holding the NetTiers Lists. So when multiple forms want to show the same list the result comes from a single instance of the list. Then if any simultaneously open form modifies the list it is reflected in all other open forms. This is great stuff thanks to NetTiers modified events.

    NetTiers also provides a great way to access database stored procedures, however, I don't use them much since I don't have time to build upgrades and SQL Server patches for new versions. I usually have to generated hand coded converters for putting in place application version upgrades, really sucks doing it that way but I get paid for speed.

    Ok, now that we've covered some basic intro stuff here is my process for using NetTiers on a form.

    First thing; I love code completion so I try to steer in that direction even if it takes a few more lines on my part.

    Once you generate your database, set your config file and include references to the 3 NetTiers projects into your work project your ready.

    You'll need to compile your project so that all the NetTiers objects are available;

    Next in the form where you want to access the NetTiers classes use an include, something like;
    using Data;
    using Data.sqlClient;
    using Entities;

    Now you can put some controls on your form, say a textbox, checkbox and combobox...

    Then drag a Binding Source object to the form.
    Now set up the Binding Source object. I associate the binding source object to the actual NetTiers object I want to use. For our purpose lets consider a table named patient.

    Click on the binding source object and look for the DataSource property. Set this property equal to Entities.Patient.
    To do this, since you have not added and Data Source to your project yet, just click the drop down and chose "Add Project Data Source". Next Chose "object" then select the object from the NetTiers classes. Your NetTiers namespace will appear something like Entities. Then open the Entities leaf and find patient--or you table. And click finish.

    Now you have added your NetTiers Patient table to the project and can call it up any time you want without having to go through the wizard again.

    What we have just done by associating the Binding Source object the NetTiers Patient Table object allows use to use Code Completion. We have not actually set anything up to automatically retrieve data. We have only told the Binding Source object what type of object it should find field names from when show the developer available field names for the target table.

    Now you can set the form controls up by associating each control with the binding source and assign the various properties envolved with showing the table data. Remember we have not actually retrieved any data yet. Only notified the Binding Source object of its target table and field names to chose. You will notice when setting the necessary fields of each control that the binding source actually allows your to see fields from the table.

    For example if you had a field Patient.NameLast you would use a text object and assign this object's Text Project to Patient.NameLast. (Of course the table would have to have a "NameLast" field right? LOL

    Ok, so now you can setup your other controls like you would normally with a binding source object. There are other ways to use the NetTiers objects with your form controls but I prefer this way, fast and simple right!

    Next we need to get the data from the Database Server. This is just as simple. You could use the next steps to supply the binding source with record objects, however, a better design pattern is suggested, i'll explain later.

    Our goal here is to get a list of patients for the binding source to use and show a record. The following code gets all patients even though we are only showing a single patient record. This is so you can later and a listbox control and see how easy it is for yourself.

    Some where in your project create a PatientService class, I used a separate project to hold these types of classes, similar to the following;

    using System;
    using System.Collections.Generic;
    using System.Text;

    using Tiffany.Entities;
    using Tiffany.Data;

    namespace Services.Tables
    {
       static public class Patient
       {
          static private TList<Patients> items = new TList<Patients>();
          //Properties to access the list object
          public static TList<Patient> Items
         {
           get
           {
                    if (items == null)
                    {
                       items = DataRepository.PatientProvider.GetAll();
                       items.Sort(PatientColumn.NameLast.ToString());
                    }
                    return items;
           }

          //Code to save a patient here
          public static bool Save(Patient patient)
          {
            return DataRepository.PatientProvider.Save(patient);
          }
         public static bool Save()
         {
           return DataRepository.PatientProvider.Save(this.Item);
         }
       }
      }
    }

    As you can see from the above class there will only be a single instance of the Patient table in your system. So any changes here will be reflected by any forms or controls active at any time. I've dummied this class up some for the example but I'm sure you can see where this is going and how it helps the overall architecture of the app.

    Now back to the form, you will want to add a reference to the newly created name space and class. So add the reference by right clicking the reference folder under your startup application and adding the project then with a using directive:
    using Services.Tables;

    Now where ever appropriate in your form set the BindingSource's DataSource property to the new created static object;
    bsPatient.DataSource = Services.Tables.Patient.Items;

    Now to save your changes? Add a button and implement the following code.

    //Saving code here. works with a newly created Patient or even a previously Patient record.
    bsPatient.EndEdit();
    Services.Tables.Patient.Save();

    That's it... Ok I cheated a little. I use the voided signiture of the Save function in the NetTiers object. This function will simply look at every Patient record and save all the ones that have been modified. If we want to save only a single record currently selected by the Binding Source Object? Then we must type case the BindingSource's CurrentObject field like so;
    Add this accessor to the form or just type cast the object. I prefer the Accessor approach;

    public Entities.Patient thePatient
    {
        get{return bsPatient.DataSource as Entities.Patient;}
    //I also use the Accessor's set for later form access ease like so
        set
        {
            bsPatient.DataSource=value;
        }
    }

    The accessor allows the simple assignement back and forth of the Patient object without lots of casting in the code.

    Ok, hope this encourages you to use NetTiers. I've found it simple and easy to use, most of the time. But still wish they would immpliment a few more features. Nothing can be perfect I guess.

    Have a blast!

    secret
    • Post Points: 35
  • 10-27-2007 4:12 AM In reply to

    • fweeee
    • Top 25 Contributor
    • Joined on 08-08-2007
    • Posts 187
    • Points 4,608

    Re: Tutorial for building a windows forms application

    JRich:
    This inheritance exposes all of those protected properties you need. Again, if you haven't done this before, I can send you a write up on how to do it.
     

    JRich,

     I'm finally getting stuck into this development, and going back over my old posts. This sounds interesting, but I dont know much about doing this. (Inherting controls and the like). Can you provide a little more information? 

     Thanks.

    ---- EDIT ----

    Actually, never mind. I worked it out after a few minutes of searching. But this is not going to be very practical for me, as my application need to be multi-lingual, and having the captions for all the fields in a single control is not going to facilitate this.

    • Post Points: 5
  • 10-29-2007 7:54 PM In reply to

    • fweeee
    • Top 25 Contributor
    • Joined on 08-08-2007
    • Posts 187
    • Points 4,608

    Re: Tutorial for building a windows forms application

    mathisr:
    NetTiers is great! There are a few kinks to work out, especially since I'm a newby, but after getting the config file set, reviewing some samples and working with it I'll never go back to CSLA.
     

    Can I ask what samples you are refering to? (that you reviewed). I have tried to find samples of nettiers in a winform environment and have not had much luck. 

    • Post Points: 35
  • 10-30-2007 10:28 AM In reply to

    • mathisr
    • Top 150 Contributor
    • Joined on 03-05-2006
    • Posts 32
    • Points 490

    Re: Tutorial for building a windows forms application

    Actually I had no samples to review, I just plowed ahead and learned and I went.
    However, If you think it would help I could provide you some simple forms I have built. But they are based on sql server.

    It really is simple, just associated your Binding Source object with the NetTier entity objects.
    Then make sure in the form load, or somewhere, you assigne the Binding Source object's DataSource property with the NetTiers List object.

    Really you can even bind a single NetTier's object entity object to the Binding Source object. Really cool stuff.

    secret
    • Post Points: 35
  • 10-30-2007 11:18 PM In reply to

    • fweeee
    • Top 25 Contributor
    • Joined on 08-08-2007
    • Posts 187
    • Points 4,608

    Re: Tutorial for building a windows forms application

     Well, I'm happy to get any assistance I can. I am spending far to long working out what are probably relatively simple problems, and it is very frustrating.

    Right now I'm thinking I'd be willing to pay for assistance with nettiers - either a step-by-step tutorial, a sample application (Using all the right practices), or even "consulting".

    • Post Points: 35
  • 11-01-2007 6:27 AM In reply to

    • mathisr
    • Top 150 Contributor
    • Joined on 03-05-2006
    • Posts 32
    • Points 490

    Re: Tutorial for building a windows forms application

    The NetTiers has put in a lot of work provide free support and this forum has helped me very much. So I will follow their lead and help if I can too.

    So how can I help? What type of database/server are you using? What are you needing help with? With this information I can either put together a few samples or maybe even provide some tutorial video. But I don't think you'll need much help with NetTiers after getting the jist of it.

    As for (Using all the right practices) I'm only an MCP and continue to learn from others in regards to architecture design and delpoyment. However, some times the best practice is what works to get your solution/project complete. After all we have to make a living right? LOL!

    Russ

    secret
    • Post Points: 35
  • 11-01-2007 7:07 AM In reply to

    • fweeee
    • Top 25 Contributor
    • Joined on 08-08-2007
    • Posts 187
    • Points 4,608

    Re: Tutorial for building a windows forms application

    Russ,

    Thanks for your reply,

     Well lets see, at the moment I'm trying to come to grips with basic record navigation/validation/error handling type stuff. I'm kind of coming to grips with record navigation, but my error handling leaves a lot to be desired. In a previous posting, I was asking why an error I was getting gave no clue about the cause. I was told it was something to do with my config file, but the advice that was given didnt seem to help (http://community.codesmithtools.com/forums/p/7554/28444.aspx#28444).

    The thing that I'm trying to investigate now is creating a many to many relationship between two tables. Originally I want had the two foreign keys as the primary key (two field primary key), but I have since learned this is a no no - I should have a single field primary key which the user cant touch, and then just have the two foreign keys as a unique index. Now I'm trying to work out how to gracefully recover from the user trying to put in a duplicate record (that is, a record with the same values in the foreign keys, braking the unique constraint).

    I'm also after the best way to automatically save records in a datagridview automatically as the user leaves the line, in a way that gracefully tells them if there is an error and forces them to go back and fix it.

    Thats as far as I have gotten so far. Surprisingly, those two points have held me up for days now. I want to make sure I find the right way of doing it, rather than just fudging my way through a half assed solution. 

    Any assistance would be much appreciated. 

    • Post Points: 65
  • 11-01-2007 10:23 AM In reply to

    • mathisr
    • Top 150 Contributor
    • Joined on 03-05-2006
    • Posts 32
    • Points 490

    Re: Tutorial for building a windows forms application

    Ok,

    Just peeked in, so don't have much time, at the moment.

    But we can start with the navigation/validation/error handling;
    If you are familiar with Visual Studio's standard errorProvider object and your taking advantage of the the standard Binding Source object you should start there. The Error Provider object will work hand-in-hand with the NetTiers error features. Basically, NetTiers allows you to create custom error handlers, with its Validation Rule Engine, for each of your table's fields. Some error handling is automatically created for you; ie field length and type. So to help defeat these errors you should set the associated properties in each control. For example if you try to update a text field that has a max length of 30, in your database definition, and your user input control allows for 40, then you'll get an error. Maybe the errors your describing already.

    To put the error provider in place drag it from the toolbox then associated it's DataSource property with the proper BindingSource. Next, each input control will allow you to set the simple text displayed when an error occurrs. Read on the Error Provider feature for Visual Studio, it is not difficult and should only take about 15 min. This simple Error Provider object can save you lots of time!

    Also spend some time researching the NetTiers Validation Rule Engine;http://wiki.nettiers.com/EntityLayer.ashx#Entity_Validation_Rule_Engine_17

    You'll notice NetTiers generates the basic Validation Rules for you; ie field length and type.

    The standard DataGridView object has several events to help in validation especially; RowValidating and CellValidating. Review these events and see if they help? You can also use the NetTiers Validation Rules from these events to reduce some of the druge work. You can call the NetTiers Entity object or the TList to determine validation of and individual object or the entire list;

    TList<People> people;
    ... fill your list here code
    if( ! people.IsValid ) { ... fix the problems here code. }

    Foreign keys?
    Yup, these can be a hassle if your using compound fields. I would suggest you reevaluate your design and determine the fallout from always creating a unique Identifier for every row. I have found it to be much simpler to implement single indenties for each table then build stored procedures or processes for features you might require. Multi-sided relationships complexities and thier associated coding becore a lot simpler, especially if you don't have a complete archeticure in place yet.

    Ok, back to work for me. I'll check back on your status in a bit.

    One thought befor I go,  I'm not certain if all your questions will be related to NetTiers and if the forum would appreciate us clobbering there thier space with our correspondence. Perhaps we should use email or Im, up to you.

    MS Messenger Id: Russ_Mathis@Hotmail.com

    secret
    • Post Points: 5
  • 11-01-2007 8:16 PM In reply to

    • TFOGARTY
    • Not Ranked
    • Joined on 06-07-2007
    • Posts 5
    • Points 170

    Re: Tutorial for building a windows forms application

    Guys,

    Am in a very similar situation to fweeee in that I would like to see some tutorials/samples especially related to Datagridview. I'm somewhat further down the road in my app than fweeee in that I'm kinda familiar now with the templates and some of what they can do. For example, I'm developing a data driven app with datagridview as the basic "unit" for displaying data. I'm able to add/delete/undo etc and validate with my own custom functions using the Validationrules etc.

    My problem is this - I don't think I'm doing a lot of it right or at least I'm not sure because I'm seeing issues pop up that make me think, for example that the way I'm adding records into the grid is causing me problems. When I add an object, I was using the bindingsource.Add(object) method. This would add a row to the datagrid and create an object for what I wanted. This worked fine. But using this process for adding, I'm having issues with getting a worthwhile "undo" process. I can use the CancelChanges() method of each object to (believe it or not) cancel the changes made by the user, but that won't work for removing any new objects added but not saved. I also noticed that I need to re validate each object because even after cancelling changes the broken rules still exist and I need to force a revalidation to get rid of the red icons that appear  in the datagrid. I suppose the question I have is this. What is best practice for adding, undoing and deleting.

     Incidentally, While I'm at it, I think I'll put this one out there as well. As part of the app I'm using the Krypton MDI interface. When I add a new page I just stick a user control with my datagridview etc. on it and it opens up displaying the data the user wants. If I invalidate a cell by, say, changing an existing record to have a blank value it (rightly) displays the red icon and gives the tooltip with the message I want. However, if I close that page (using the x on top right) and then open it again using the button in the main interface of my app the data displays as it did before except there will be a red icon beside the field that I changed, even though it's value is fine because I've reloaded it from the database. If I check the broken rules list it still has broken rules so even though the initial objects were (seemingly) destroyed the validation isn't. Should I undo all changes since last save as I close the form (and thereby validate as well) or should I validate each object as I add it to the datagrid or is there some sort of disposal I should do when the form is closing?

     I'd appreciate access to any samples or best practices - I don't think what I'm trying to achieve is very advanced or unusual, especially in the context of using a datagridview. You seem to have some samples to offer Russ but I realise that some of what I'm looking for is specific to a control you may not have worked on (DataGridView). Maybe there are others who have worked extensively on it. I'd be surprised if there isn't.

    Thanks in advance for any help.

    Tom.

    • Post Points: 5
Page 1 of 1 (13 items) | RSS
Copyright © 2008 CodeSmith Tools, LLC
Powered by Community Server (Commercial Edition), by Telligent Systems