"WPF Composites simplifies WPF development. Think of graph paper and plotting at X-Y."


WPF Composites is a project designed to provide an alternative, concise, C# code-behind approach to managing UI Framework Element composites. Composites are normally managed via XAML and DataTemplates but this library uses ID's and X-Y Coordinates instead to position elements on the screen. This is currently for synchronous apps only. It is not designed to be thread-safe. This library is still alpha and under-construction. However, I welcome volunteers!

It works via 100% code-behind, zero XAML, has CSS-like Selectors, has Generators to generate multiple Framework Elements based on a single Prototype Element's properties (e.g. create a button and automatically clone it 5 times), and supports 22 different WPF controls. Just added sorting to the panels too to allow sorting Grid, StackPanel, DockPanel, WrapPanel, TreeView, and DataGrid. Current platform is Windows 7 with .NET 4.0.

Current Status
Version 4.0.0 has been released! I'm very excited about this one. Both the Selectors engine and the Generators turned out great in my humble opinion. I also improved the Events and the Demo App.

This is still alpha just because there may still be some additions in terms of supporting more controls. However, it could already likely be used for WPF prototypes, demos, tiny apps (e.g. in-house tools for your team?) The core has solidified. Next, is more just rounding out the functionality and enhancing it.

WINRT NOTE 4/26/2013: I've taken a look at porting this library to WinRT and I think it may not be a good fit considering the apparent needs for UI virtualization, async optimization, and keeping up with a codebase that may be changing a lot every year-on-year (e.g. Windows Blue.) So, my plan at the moment is to stay focused on WPF Composites (which can still run on the Windows 8 Desktop) while foregoing any WinRT Composites.

See C# Demo App Screenshots here: Demo App Screenshots
This library isn't limited to C#. See an IronPython example here: Iron Python Example
Remaining To-Do Items: To-Do List
Tutorials and Details: Dictionaries, Easy as 1-2-3-4-5, Selectors, Events, How-To Examples, Generators (Prototypes), Memory Profile, Sorting
Architectural Discussion: Model-View-Presenter

For Silverlight, allow me to refer you to fluent-silverlight? This appears to take a somewhat similar fluent-interface code-behind approach, only focusing on UserControls and retaining WPF Databinding, WPF Commands, and MVVM:
http://code.google.com/p/fluent-silverlight/


BEGIN COMPOSITE . . . END COMPOSITE
Below is an example for creating a new composite, adding a new Rectangle (automagically instantiating it) to the composite, followed by adding two Textblocks underneath the Rectangle (all in column 0):

myDockPanel.BeginComposite(myGuid)
                .AddAnything<Rectangle, DockPanel>(0,0)
                .AddText(1,0, "Hello World 1")
                .AddText(2,0, "This is text at Row 2 Column 0 in the composite")
                .EndComposite(new DockArgs(Dock.Left));
The entire composite is then added to myDockPanel at Dock.Left. myDockPanel is an IParent. IComposites are added to IParent controls. IComposites are containers for Child elements.

Typically, objects retrieved from or saved to a SQL database will have a record ID associated with them, either a GUID or a basic IDENTITY number (1-...). It follows then that composites of UI Elements on the screen may also readily be associated with this same ID, the same ID as that used in the database. However, a GUID is not required (as one can be created automatically behind the scenes.)

This can be an effective way of binding and retrieving a composite set of UI Elements (which may correspond to properties within a C# Class.) Within a single composite tied to an ID, identify X-Y Coordinates for positioning child elements within a Grid within a parent container.


ICOMPOSITE CONTAINER TYPES
Currently, I support multiple containers (each implementing IComposite) for use within a composite.
public enum ContainerType
{
     HorizontalPanel = 0,
     Grid = 1,
     WrapPanel = 2,
     DockPanel = 3,
     VerticalPanel = 4,
     ContentControlPanel = 5,
     Canvas = 6,
     UniformGrid = 7
}

//Define the container to use upon initializing an IParent
myDockPanel.Initialize(100, 100, ContainerType.Grid, . . . 
The X-Y Coordinate obviously ties to Rows and Columns when using a container type of Grid, but here is a full breakdown for all the different IComposites:

Grid: x-y maps to row-column
HorizontalPanel, VerticalPanel, WrapPanel, UniformGrid; x is ignored (should be 0), y maps to index of Children
DockPanel: x maps to the Dock enum by int: Left = 0, Top = 1, Right = 2, Bottom = 3; y maps to index of Children
ContentControlPanel: there is only one x-y and that is 0,0 for the single Child
Canvas: x maps to distance from Top, and y maps to distance from Left.
Remember that x-y coordinates must be unique per child item; i.e., you can't have two items share the same x-y coordinate since this is used as a unique key to store and retrieve by.

It is important to note also that each "composite" is wrapped in a Border. This is always the top-level Type of the composite. In this way, the Border may play a versatile role similar to the DIV tag on the web?

Besides BeginComposite...EndComposite, there is also BeginSettings...EndSettings which should be defined first. These settings are stored and then applied to each item (either by Type or based on X-Y position) when BeginComposite is called. There is also support for subscribing/unsubscribing events.

I started with a working example of this code-behind approach via extensions to the WPF ListBox. I used extension methods because I didn't want developers to have to implement a new custom control.
This humble start has grown into fair support for 22 IParent controls:

Code Examples
ListBox Example
Grid Example
Dock Panel Example
Combo Example
Menu Example
Tree View Example

Supported Controls
These controls are official IParents.

IParentGuide.png

Other Compatible Controls

These controls are NOT official IParents but they may not need to be; e.g., if a control is more atomic. Below are controls that are such compatible controls that are showcased in examples in the Demo App:

1. Extended WPF Toolkit™ Community Edition DataGrid
2. Extended WPF Toolkit™ Community Edition DecimalUpDown (Format strings include C-Currency, F-Fixed Point, G-General, N-Number, P-Percent)
3. Extended WPF Toolkit™ Community Edition MaskedTextBox (For fixed-length formatted strings such as phone number or social security number)
4. Extended WPF Toolkit™ Community Edition MultiLineTextEditor
5. System.Windows.Controls.TextBox
6. System.Windows.Controls.DatePicker
7. System.Windows.Controls.ComboBox
8. System.Windows.Controls.Border (leveraged as a "flat button" for easy styling with colors, mouseovercolor, etc.)
9. System.Windows.Forms.DataVisualization.Charting.Chart

Caveats

The DataGrid support is for Composites in a DataGrid at this time.

For a regular DataSet, in contrast, I merely provide basic examples using the free, open-source DataGrid available from the Extended WPF Toolkit™ Community Edition here: http://wpftoolkit.codeplex.com/
In other words, the cells in a DataSet-based DataGrid are NOT considered "composites" but atomic values. The DataGrid itself could be added to a Composite such as it is added to a StackPanel in a TabControl in the Demo App. It is convenient to use this separate DataGrid for this purpose since it resides in a separate namespace.

Also, one more small note: in the demo app, AdornerDecorator is leveraged for field validation of TextBoxes, showing an example that dynamically displays a red box around invalid fields. In the DataSet-based DataGrid, I handled things differently--I merely added an extra column for displaying validation-related error messages. In general, I've avoided leveraging WPF Validation Rules and IDataErrorInfo primarily due to lack of time on my part to consider a "WPF Composite"-esque way to leverage them

Potential future IParent controls that are not currently supported at this time may include ViewBox, StatusBar (this can be achieved with a horizontal stackpanel?), Ribbon, NavigationWindow, ContextMenu, RichTextBox, and FlowDocumentViewer. These controls could still be used in a WPF Composites app just not as IParents yet.

Ideally, these parents shouldn't just implement IParent, but should also have a thorough set of "convenience" extension methods as well. I could use a lot of help implementing each. If you would like to "adopt a control" to fully extend and support, please let me know!

COMPOSITE STRUCTURE

The different container types are added at the end of a ContentControl. This ContentControl is wrapped in a Border:
Composite.png

COMMON COMPOSITE SCENARIOS

Here is a breakdown of several common Composite scenarios. It can occasionally be confusing to think about how to nest complex Composites or build up chains of IParents and Composites. Hopefully, this may be a helpful guide:
CommonCompositeScenarios.png

RECOGNITION

I have to recognize Sacha Barber whose CodeProject article informed my work the support for ScrollViewers: http://www.codeproject.com/Articles/37366/Styling-A-ScrollViewer-Scrollbar-In-WPF
Thanks Sacha for the great article regarding how ScrollViewers/Scrollbars are structured!

Also, I must recognize Bart De Smet from Microsoft for his concept of MinLINQ (http://community.bartdesmet.net/blogs/bart/archive/2010/01/01/the-essence-of-linq-minlinq.aspx) which insipired my thoughts on the IParent interface. It struck me that I could likely benefit from creating methods in the interface similar (at a high-level) to the Ana (generate), Bind, and Cata (map/reduce) methods of Bart's MinLINQ, and that's the path that I have gone down. Because, when you think about it, every composite is like an IEnumerable over a set of UI Elements, so the bare minimum you'd need to implement LINQ-to-Composite-Child-UI-Elements would be Ana, Bind, and Cata :-)

Credit to Sam Jackson for his Trampoline blog post and code here which I may use in part inside a new stack-friendly recursion helper that I may write for recursing controls (to enable CSS-like Selectors):
http://blog.functionalfun.net/2008/04/bouncing-on-your-tail.html

Credit to Marlon Smith for giving me the trick for displaying the non-modal dialog via a Canvas, Z-Index and Attached properties.

I would like to recognize Xceed http://xceed.com for their generous contribution of the DataGrid to the free, open-source Extended WPF Toolkit™ Community Edition here: http://wpftoolkit.codeplex.com/
I am not affiliated with Xceed in any way other than as a fan. I've heard good reviews of their WPF DataGrid and so I decided to include their open-source version in the WPF Composites demo app. I use this DataGrid, in particular, to display examples leveraging DataSets rather than Composites since WPF Composites need not be used everywhere or for every case. One might also consider that DataSet column values are typically scalar/atomic rather than composite?

Kudos to Josh Smith for the Thriple Project which I incorporated support for (the ContentControl3D IParent.) This codeplex project is available here; http://thriple.codeplex.com/

Last edited May 12 at 6:12 AM by stagathome0069, version 409