CurionLib Dynamic Data Entry Forms





5.00/5 (20 votes)
Dynamic data forms.
Introduction
One feature of CurionLib
creates a simple data entry form fairly quickly. On the simple side, its data meets control, out pops a ui. It supports editing a single object as well as collections of objects. It's fairly extensible and was designed to allow a fair amount of design-time and run-time customization.
This article and two others are included in the documentation directory of the library.
There are four sample applications. Demo.plain and Demo.mui use Demo.common and have the same content. Demo.plain has very little styling. Demo.mui uses Modern.UI for styling. Demo.designer shows a several settings that can be used to customize a form. Demo.tiny is a small app that is one step beyond the sample app below. It shows using a collection, navigating, adding, deleting, and custom commands.
Getting Started
The proof, as they say, is in the pudding. So what does it actually take to get a form off the ground?
- Add a reference to CurionLib.dll.
- Add a
ItemForm
control to a Window or User Control:- If you will be adding many of them, you can add the controls to the tool palette by right clicking, selecting Choose Items and picking the CurionLib.dll. Once in the toolbox, you can simply drag onto a form
- Add a
namespace
to the definition:xmlns:curion="http://curion.net/Forms"
Add the form:
<curion:ItemForm x:Name="ctlForm" />
- Create a class.
- Set
ctlForm.DataContext
to an instance of the class.
Here's the completed Window:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:curion="http://curion.net/Forms"
x:Class="MainWindow"
Title="MainWindow" Height="140" Width="320">
<Grid>
<curion:ItemForm x:Name="ctlForm" />
</Grid>
</Window>
Here's a quick sample class:
Class Person
Public Property Name As String
Public Property Age As Integer
Public Sub Hello()
MsgBox(String.Format("Hello {0}. I see you're {1} years old.", Name, Age))
End Sub
End Class
And the code on your form:
Class MainWindow
Sub New()
InitializeComponent()
ctlForm.DataContext = New Person
End Sub
End Class
If all went well, you should see something like this when you run the app:
Enter your name and age and click the Hello button and you should see a message box confirming your name and age.
Continuing a bit further, Demo.tiny extends the example by using a collection of people, adding navigation, add, delete, and display current record contents. It looks like this:
I know you're probably thinking, these weren't very exciting. The good news is there's a bit more to the control, hang on a bit.
Organization
The code is organized in a few namespaces.
Curion.WPF.Controls
- Most of the controls.ActionStack
- A custom control class that creates a list of buttons from anonymous methods.CommandStack
- A custom control class that creates a list of buttons for each method in theCommandSource
with no parameters.ContextDefaults
- A class that localizes changes toDefaults
. Designed to be used in aUsing
block to temporarily change defaults for example when creating a form.DynamicCommand
- Creates a command for each no parameter method inCommandSource
that can be executed by name.Filter
- A custom control class that is not intended to be used directly. It is anICollectionView
filter control that consists of aTextbox
(the filter), aTextBlock
(the count of items), and aCommandStack
(optional buttons that do stuff).FilterList
- A custom control class that filters items in aListBox
based on the text entered.MappedContentButton
- A factory class that creates a button and can optionally use mapped values or functions to create content for the buttons.MemoryDefaults
- A class that implementsIDefaults
. A memory based implementation ofDefaults
which is used to supply initial values for various classes.mSupport
- A few shared support routines.MyCornerRadiusConverter
- Convert corner radius to and from 1, 2, or 4 values.MyGridLengthConverter
- Convert grid length to and from string. Supports A=Auto, #*=Star lengths, #=Pixels.MyThicknessConverter
- Converts thicknesses to and from 1, 2, or 4 values.NamedBrushConverter
- Converts solid brushes using hex, color names, and windows system color names to and from stringsNamedColorConverter
- Converts colors using hex, color names, and windows system color names to and from stringsSimpleButton
- A factory class that creates a basic button.StringTitleConverter
- Converts csv separated alignment and text to and from a FrameworkElement. ex: Center,My Title or Right,My Title
Curion.WPF.Controls.Form
- Classes used by the form controls.BooleanCheckBoxColumnFactory
- A factory class that creates a checkbox control.BooleanToggleColumnFactory
- A factory class that creates a toggle button control.BorderColumnFactory
- A factory class that creates a border control.ButtonColumnFactory
- A factory class that creates a button control.ColorColumnFactory
- A factory class that creates a color textbox control.ComboBoxColumnFactory
- A factory class that creates a combo box control.CornerRadiusColumnFactory
- A factory class that creates a corner radius text box control.DateColumnFactory
- A factory class that creates a date picker control.DecimalColumnFactory
- A factory class that creates a decimal text box control.DoubleColumnFactory
- A factory class that creates a double text box control.ExpanderColumnFactory
- A factory class that creates an expander control.GridLengthColumnFactory
- A factory class that creates a gridlength text box control.GroupBoxColumnFactory
- A factory class that creates a group box control.HeadingColumnFactory
- A factory class that creates a heading control.HorizontalAlignmentColumnFactory
- A factory class that creates a horizontal alignment combo box control.ImageColumnFactory
- A factory class that creates an image control.IntegerColumnFactory
- A factory class that creates an integer text box control.IntegerSliderColumnFactory
- A factory class that creates an integer slider control.ItemForm
- A custom control class for a single item form.ItemsForm
- A custom control class for a form with a collection of items.ListBoxColumnFactory
- A factory class that creates a list box control.LongColumnFactory
- A factory class that creates a long control.MakeCsvColumns
- A factory class that creates a list of control factories for each read/write property matching a csv list using mappers.MakeCsvForm
- A factory class that lays out controls for a form using a special line by line csv layout. csv layouts allow placing multiple controls on a single line. May contain a title and places; headings (#
), horizontal rules (-
), blank lines (_
), buttons ({[-|+|*][header=]methodName}
) and columns (columnName[=width]
) using the csv layout.MakeSimpleColumns
- A factory class that creates a list of control factories for each read/write property using mappers.MakeSimpleForm
- A factory class that lays out controls for a form from top to bottom. May contain aTitle
if specified and will layout buttons on the form (on top by default). Use in conjunction with MakeCsvColumns to limit the columns displayed or change the prompts.MakeSimpleHeader
- A factory class that makes a label for use as a header on a form .MakeXmlForm
- A factory class that lays out controls using a simple xml layout. xml layouts allow creating boxed regions. The regions (group
) can be oriented vertically or horizontally (columns
) and place controls within the region by using a csv layout (csv
). Regions may beGroupBox
,Expander
,Border
, orClear
(no decoration) regions. The csv layout is fromMakeCsvForm
.ManageArrayItems
- Manages adding, deleting, and retrieving a view for an Array collection.ManageArrayListItems
- Manages adding, deleting, and retrieving a view for an ArrayList collection.ManageClassColumns
- Manages retrieving a list of columns, getting column type, getting and setting column values for an object.ManageCollectionItems
- Manages adding, deleting, and retrieving a view for a Collection collection.ManageCollectionView
- Manages adding, deleting, and retrieving a view for a CollectionView collection.ManageDataListItems
- Manages adding, deleting, and retrieving a view for a Curion DataList collection.ManageDataListRowColumns
- Manages retrieving a list of columns, getting column type, getting and setting column values for a curion data list row.ManageDataRowColumns
- Manages retrieving a list of columns, getting column type, getting and setting column values for a data row.ManageDataTableItems
- Manages adding, deleting, and retrieving a view for a DataTable collection.ManageDataViewItems
- Manages adding, deleting, and retrieving a view for a DataView collection.ManageDictionaryColumns
- Manages retrieving a list of columns, getting column type, getting and setting column values for a dictionary of values.ManageDynamicObjectColumns
- Manages retrieving a list of columns, getting column type, getting and setting column values for a dynamic object.ManageExpandoObjectColumns
- Manages retrieving a list of columns, getting column type, getting and setting column values for an expando object.ManageGenericItems
- Manages adding, deleting, and retrieving a view for a generic collection aka List(Of Type), ObservableCollection(Of Type), etc.MarginConverter
- Convert margin to and from 1, 2, or 4 string values.MemoColumnFactory
- A factory class that creates a memo field control.SelectIManageColumns
- Select column manager.SelectIManageItems
- Select collection / items manager.SingleColumnFactory
- A factory class that creates a single text box control.SolidBrushColumnFactory
- A factory class that creates a solid brush text box control.StringTitleColumnFactory
- A factory class the creates a title textblock control from text and alignmentSuspendFormGeneration
- Class that suspends form generation, designed to be used in ausing
block while initially configuring a form.TextBoxColumnFactory
- A factory class that creates a text box.ThicknessColumnFactory
- Convert thickness to and from 1, 2, or 4 string values.DateRules
,DecimalRules
,DoubleRules
,IntegerRules
,LongRules
,SingleRules
,TextRules
- Classes that implement basic validation rules for data entry controls
Here's a quick reference of the form classes:
Curion.Data
- Some miscellaneous data classesDataFilter
- A data class that provides column names, values, and parameter names. Used bySQLTable
to filter data.Parameter
- A data class that provides column name and value. Used to pass parameters to SQL Server.
Curion.Data.Sql
- Some SQL Server support classesSqlTable
- A class that provides a simplified method of creating aDataList
for a SQL Server table and saving changes.SqlSupport
- A module with some SQL Server support routines.
Curion.Data.List
- Classes that supportDataList
DataList
- A dynamic object class similar in usage to aDataTable
.Column
- A class that represents a column in aDataList
.Row
- A class that represents a row in aDataList
.ColumnCollection
- A class containing a collection ofColumn
for aDataList
.RowCollection
- A class containing a collection ofRow
for aDataList
.CompareRow
- A class that compares two rows of aDataList
using a list ofOrderItem
. Used when sorting aDataList
.OrderItem
- A class that tracks a column name and sort direction. Used when sorting aDataList
.

In addition to the classes, there are a number of interfaces used:
IMakeButton
- An interface for making a button. Used by button creating classes.MappedContentButton
andSimpleButton
implement this.IMakeControl
- An interface for making a control. Used by theIMakeColumns
interface.IFilterView
- An interface for filtering a view.FilterText
andView
will be set and then theFilter
predicate will be retrieved and used to filter the view. Used byItemForm
.FilterViewFields
implements this.IDefaults
- An interface defines how Defaults are accessed.ContextDefaults
andMemoryDefaults
implement this.IMakeColumns
- An interface for creating column factories.MakeSimpleColumns
andMakeCsvColumns
are implementations of this.IMakeForm
- An interface for creating form factories.MakeSimpleForm
andMakeCsvForm
as implementations of this.IMakeHeader
- An interface for creating header factories.MakeSimpleHeader
is an implementation of this.IGetData
- An interface for retrieving data.SqlTable
is an implementation of this.IHandleChanges
- An interface for handling changed data.SqlTable
is an implementation of this.
Terms
Here's what I mean by a few of the terms I've used:
Defaults
-Defaults
are a collection of values used to drive the initial properties of new classes.Defaults
can be changed globally or in a limited scope.Factory
- Factories are classes or methods that create classes, methods, or values.Mapper
-Mapper
s select items to be used in a particular context. For example in theMakeSimpleColumns
class, theColumnMapper
maps data types to column factories and theColumnMapperException
maps specific column names to column factories. In this application, most mappers map a key, such as a datatype or column name, to a function. Using anonymous methods, this allows a high degree of customization of the factory instantiation.Header
- The prompt that is normally displayed before a field.Column
- A factory that creates a .NET control.
What Does It Work With
ItemForm
was designed to work with a single object. To use a single object, set the DataContext
property. It has been designed to work with a POCO (plain old CLR object, i.e. your class), ExpandoObject
, DataRow
, DataList Row
, DynamicObject
, or Dictionary
.
ItemsForm
was designed to work with collections of objects supported by ItemForm
. To use a collection, set the ItemsSource
property. The View
property will be available that will return the current ICollectionView
in use.
For POCO collections, each item can be of a different type and a new UI will be created for each. While this can be pretty cool in certain circumstances, one of the downsides is that RepeatButtons
don't really work well, since they're re-generated for each new class / form.
Using the Control
There are two demo applications that show the controls in use. DemoApp
is a generally unstyled WPF application to give you a feel for what it looks like out of the box. Wherever possible, I've used control wrapping to extend controls as opposed to inheriting controls. The result of this is that it should be fairly easy to use your Theme with the control. DemoAppMUI
is an example of using a theme, MUI or Modern.UI in this case.
Both applications use Customer.xml in a few places. It's a small XML file with 1,000 randomly generated customers and a few data types.
DemoApp
Shows using single objects, lists of objects with a custom pager, and lists of objects using a ListBox
pager. Madness demonstrates using a list containing multiple types with one or more methods. And finally Separate command object demonstrates some basic overall form customization and using mapped content buttons.
All of the forms except Madness use the customer.xml records and can be displayed as a simple form, csv layout, or xml layout form by selecting the corresponding option button in the upper left corner of the app.
DemoAppMUI
Demonstrates the use of single and multi-item lists with theming which is provided by mui. The pages that are displayed are in the Pages folder and organized roughly the same as the menu. Of particular note:
- Custom/CSV form which shows many of the features including headers, listboxes, options, and mapping to enums.
- Custom/List Nav and List Nav2 which show customizing separators.
- Custom/MiscControls which shows a filtered list box.
- And utility which is another example similar to the first one that generates basic dependency properties. It also demonstrates creating a default button.
MakeCsvForm
One of the controls with a good deal of customization is the MakeCsvForm
control's layout. Here's a quick overview of the meaning of the lines. Note that text in [] are optional except as noted for the CommandButton
.
- * - Create a repeat button. Cannot be used with + or - prefixes.
- + - Create a default button.
- - - Create a cancel button.
- # - A fixed width in pixels, i.e., zipcode=80
- #* - A proportional width in pixels. ex: address=1*
- A - Auto-sized to contents.
#Heading | Displays a header. Must be the first entry on a line and is considered to be the only entry on the line. |
- (dash) | Draws a horizontal rule. Must be the first entry on a line and is considered to be the only entry on the line. |
_ (underline) | Puts in a blank line. Must be the first entry on a line and is considered to be the only entry on the line. |
{button1[,button2...]} | Places one or more CommandButton s (buttons for methods with no parameters) on a single line. In the current implementation, buttons will grow up to 640 pixels wide and then wrap. A button can have the following prefixes:
In addition, buttons take the form of either |
column1[=width][,column2...] | Places one or more columns on a line of the form. column1 is assumed to be the name of a column in the current object. width can take the following forms:
If omitted, a width of 1* is assumed. |
DemoApp
uses the following layout:
Name,Phone=100
-
Address
City,State=50,Zipcode=80
-
Balance=100,Added=100,IsActive=23
{First,*Prior,*Next,Last,,Show}
Update 1.0.0.1
Added IntegerSlider
, BooleanToggle
, BorderColumn
, ExpanderColumn
, GroupBoxColumn
, MakeXmlForm
. Two breaking changes header character was changed from > to # for csv layouts, and button maker is now a factory function. Other misc changes, see 0Changes.txt for more info.
MakeXmlForm Added MakeXmlForm
- <cols [height="value"]> - Arrange child nodes as columns.
- <box [width="value"] [title="value"] [type="expander|groupbox|border|clear"] [isopen="true|false"]> - Group child nodes in a box container specified by type.
- <csv [width="width"]> - generate a csv layout. InnerText is the csv layout.
Xml layout from sample applications
<layout>
<cols>
<box title="Person" isopen="true" type="expander">
<csv>
Name,Phone=100
</csv>
</box>
<box title="Misc" width="214" isopen="true" type="expander">
<csv>
Balance=100
Added=100
IsActive=23
</csv>
</box>
</cols>
<box title="Address" type="expander">
<csv>
#Address
Address
City,State=50,Zipcode=80
</csv>
</box>
<csv>
_
{First,*Prior,*Next,Last,,Show}
</csv>
</layout>
Update 2.0.0.0
Changed version to 2.0 because of the number of breaking changes, title change, and splitting the form into two controls. Here's some of the changes, see 0Changes.txt for the rest.
Breaking Changes
- Renamed
IMakeColumn
toIMakeColumns
to clarify intended use. - Moved
ButtonMaker
toItemForm
. - In
MakeXmlForm
, renamedlinegroup
tocolumns
,container
tobox
, andlines
tocsv
. - Split and renamed
DataForm
.ItemForm
has aDataContext
takes a single item.ItemsForm
has anItemsSource
with related routines. Should be more clear when using controls. IMakeColumns.Create
initial parameter changed fromobj As Object
tobase As ItemForm
. This was done to facilitate re-usingItemForms
ability to return a list of column names and retrieve the values for those columns. This should ultimately also provide greater flexibility in writing column generators.- Updated the
Create
method ofIMakeHeader
interface to include anItemForm
and column name. Should allow for more customization of headers. - Changed command button delimeters from [] to {}. Should make documentation easier to read...
- Added
ColumnNames
toItemForm
, returns column names for currentDataContext
object. - Added default property
Item(columnName As String) As Object
toItemForm
. Can get/set property values of currentDataContext
. - Added
IMakeControl
and updated column generators (MakeCsvColumns
,MakeSimpleColumns
) to selectIMakeControl
interfaces instead ofBaseColumnFactory
. - Added navigation and Add, Delete to ItemsForm.
- Added some converters and factories for new column types.
- Added IManageItems and ISelectManageItems to handle collection navigation, adding, deleting, and retrieving a view.
- Added IManageColumns and ISelectMangeColumns to handle retrieving column names, types, and getting, setting column values.