GUI Form Creation

GUI Form Creation

Old forum URL: forums.lhotka.net/forums/t/2641.aspx


Damian posted on Friday, March 30, 2007

Does anyone know of a control or a way of auto populating a .net form with controls for all the properties in a business object? I am looking for a fast easy way of generating the front end for a lot of business objects I have. Ideally it would take the business object and create a control based on the underlying datatype of the property anlong with a label for the property name. It should be dynamic in that it builds the controls at runtime. I have came across a control which is quite close called PropertyGrid by VisualHint www.visualhint.com however this only displays the data in grid form, albeit allowing you to control which .net control to use for the underlying data type.

Bayu replied on Friday, March 30, 2007

Hi,

Recipe:

- introduce a DisplayInfo attribute (inherits system.attribute)
    - make it applicable to properties
    - and add properties as needed for your UI
    - including an identifier for the type of control to use (dropdown/checkbox/...)

<AttributeUsage(AttributeTargets.Property)> _
Public Class DisplayInfoAttribute
    Inherits Attribute

End Class

- mark all the properties in your BOs that need to be rendered with appropriate DisplayInfo attributes

- in your UI:
    - use reflection to get all properties from your BO
    - filter out those that are marked with DisplayInfo
    - read the settings on DisplayInfo in order to render the correct visualization in your UI


When you have this working you can take the next step: add support for 'foreign key' properties that are typically edited in your UI using a dropdown that is bound to a name-valuelist:
- add a flag (e.g. ForeignKey, or UseNvl) for this
- also define the type of the NameValueList that should be used in your UI
- still through reflection you can dynamically instantiate an instance of this NVL in your UI
    - either introduce another attribute to mark your factory method
    - or use a standard naming convention for your factory methods
    - either way, you can dynamically create an instance of the NVL by invoking the factory method
- all as usual, you can bind this NVL to a new bindingsource and use this to fill a dropdown that enables you edit foreign-key properties

You know what the best part is?
- with just 1 usercontrol you can edit any type of  editableroot object, as long as these objects have displayinfo attributes that inform your UI how to render
- if this control is debugged and tested basically you have tested all of your editable-root views

And of course there is a downside:
- you will have to get through some reflection to get it all to work
- and it can take a while to get this control right, but when you have one you have them all

Bayu

Justin replied on Monday, April 02, 2007

We also use attributes and a control that at runtime renders the BO but it could just as easily be used to code gen a form instead.

These attributes are not just used for UI generation but rules enforcement as well. For instance  Required, Min Length, Max Length, Coded values(NVL), Input mask(string patterns), are all specified in attributes that the UI utilizes and the BO also enforces.

We have tried to stay away from UI specific attributes such as position on form, but are considering doing that as well since they are just suggestions for the UI but can be ignored if the UI chooses. For instance if you use reflection to loop through your properties and display them a inputs on a form they should come out in source code order, but we have found that reflection actually caches the propertyinfo reference internally and if you access a propertyinfo of a property out of order before the UI generator gets to it, it will be placed at the top of the cache and come out first. So we are considering adding a TabOrder or DisplayOrder to the attribute to denote specifically which order it is to be rendered, and perhaps even more complex positioning attributes in the future(x,y).

Note this is a great boon to our development as we currently have a winform and RDL renderer for our BO and are working on a ASP.net renderer there by eleminating maintaining 3 UI's (or more) that all represent the BO in the same way but with different technologies.

Justin

Bayu replied on Tuesday, April 03, 2007

Justin:

So we are considering adding a TabOrder or DisplayOrder to the attribute to denote specifically which order it is to be rendered, and perhaps even more complex positioning attributes in the future(x,y).

Justin


Hey,

I faced the same issue, and I too did not want my attributes to become too UI-specific. So I did not specify x/y coords, but rather 'logical coords'.

So I would specify my Contact's Title, FirstName and LastName to appear in the first column at rows 1 to 3 and the Address, PostalCode and City to appear in the second column at rows 1 to 3.

In WinForms I have two controls:
- one that utilises a TableLayoutPanel
    - it is trivial to translate the logical coords to cells of course
    - but the panel also supports 2 ways of positioning the label wrt the editor:
       - the labels occur left of the editors, than each logical column expands to 2 columns in the tablelayout
       - or the labels occurs above the editors, than each logical rows expands to 2 rows and the columns simply match

- and I have a FlowLayoutPanel because sometimes I don't have room for multiple columns, in that case the logical columns are simply appended below (if the flow is vertical) or next to (if flow is horizontal) each other. Each field that should have appeared in the next column is then preceeded by a separator to maintain some consistency accross panels.

By using logical coords instead of fixed x/y coords you keep a lot of flexibility in your UI.

Regards,
Bayu

Justin replied on Tuesday, April 03, 2007

I agree that if we did implement some sort of x/y it would be logical and not tied to a specific UI technology.

We are trying to stay away from UI attributes but are starting to question why, beyond it being the "right" way to do things.

For our product it makes more sense to have have the BO define the UI as well since our UI is very regular and we are not large enough to have distinct developers for UI and BO and DB. 

Justin

DansDreams replied on Tuesday, April 03, 2007

Danger Will Robinson!  (OK, maybe you guys are too young for that).

In my opinion, the statement "For our product it makes more sense to have have the BO define the UI as well" is more likely an indication that you didn't need CSLA in the first place than it is a good way to design enterprise applications.  To me that sounds the same as saying "in our company it makes more sense to have the accounting department running the mills on the shop floor."

Don't get me wrong - I built something like that before for a web site and it was very cool and functional, but it was a fairly simple application and definitely not n-tiered.

So, I think the basic premise of having a UI determined at runtime from metadata is sound and potentially useful, but that is UI metadata and not business layer metadata.

Justin replied on Tuesday, April 03, 2007

Believe me we are taking a cautious approach, we understand n-tier design and have a successful app written in the "right" way for the time which happend to be com+ windows DNA (remeber that?).

We have realized at  least in our application design that most of what makes up the differences between one BO and another's BO UI is simply the data elements and business rules.

If you can infer the order in which the inputs on a form should be displayed from the source code order of the properties why not? Why write another object( a form object) and write glue code to bind the properties of one object to another when you could have just added a little decoration to your BO and the UI has all it needs?

Again these are just suggestions to the UI, should you need to make a different UI you can always code it by hand.

This works well for us because our UI is very regular between most entities, this may not work for others so well.

As I said we already have a functional winform and RDL renderer and they are scaling extremely well and productivity has been amazing with this design and the attributes add very little overhead to the BO.

As far as "in our company it makes more sense to have the accounting department running the mills on the shop floor.", well that is a little extreme but we are small enough that we don't have UI developers, BO developers, and DB developers or DBA's we just have developers and with this model a single developer can makes changes and test all the teirs much more quickly with fewer errors.

Justin

Bayu replied on Friday, March 30, 2007

Oh,

There is also 'The Microsoft Way'. There is an excellent explanation available in one of the early shows from DotNetRocks TV, check show #7 on www.dnrtv.com.

This is really fast, but first impressions are misleading. It is a forward-only process, so when your BOs change you can start over. Also: you will have to go through this process for every single BO, everytime again. But what it does do is give you a good impression on how MS would like you to configure your databindings properly.

Regards,
Bayu

pelinville replied on Friday, March 30, 2007

I do this for some of my stuff.
 
Reflection is your friend.  I have two forms that can handle 80% of my objects.
 
It is often kinda ugly and not user friendly.  I like Bayus idea of using attributes.  They could definatly increase the usability and look of the thing.  And they could be code generated.
 
I have better luck with code generating some of the more basic forms.  Much more control and tweakability and not much more work than doing it all at run time.
 
 

Copyright (c) Marimer LLC