WPF Composites (WPF-CPS)
may enable a Rapid-Application-Development (RAD) approach to building Fluent WPF desktop applications and/or Windows Store Desktop Apps for Windows 8*?
Windows Desktop Apps may likely continue to be superior for synchronous, enterprise and content creation
apps. In counterpoint, touch-first, Modern UI WinRT apps may best serve the arena of asynchronous, individual consumer and content consumption apps. There may, indeed, be a place for Desktop apps ongoing after all?
WPF-CPS provides an alternative, concise, C# (or IronPython or F#) code-behind approach to managing WPF UI Framework Element composites. WPF 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. 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 26 different WPF controls. Just added sorting to the panels too to allow sorting Grid, StackPanel, DockPanel, WrapPanel, TreeView, and DataGrid. * I haven't actually submitted a desktop app to the Windows Store using WPF Composites. I can't vouch for whether an app created with this library would readily pass or fail the stringent Windows App Certification Requirements. I am not liable for any success or failure in attempting to get your app certified. Certification details:http://msdn.microsoft.com/en-us/library/windows/desktop/hh749939.aspxAddress Book Demo - Desktop Application
Below is a screenshot of a full-featured
demo desktop application that I wrote in F# leveraging WPF-CPS:
Feel free to try out this demo application (at your own risk, of course) here:Address Book DemoAddress Book Demo Source CodeWPF Composites Contrib
I recently added a supporting project to WPF Composites (WPF-CPS) to allow exploring/building out new controls and techniques which leverage this existing code library.https://wpfcompositescontrib.codeplex.com/
The first contribution is an experimental Squares Navigator
, a kind of data visualization control similar to paging. Each square represents 1/400th
of a very large dataset. In this example, I leverage a dataset of around 39,000 mutual fund records
provided by the SEC for free at data.gov here:
http://catalog.data.gov/dataset/investment-company-series-and-class-informationLINKSStatus UpdateWINRT Note
See C# Demo App Screenshots here: Demo App Screenshots
, also see Hello World
This library isn't limited to C#. See an IronPython example here: Iron Python Example
and an F# example here: F Sharp Example
Remaining To-Do Items: To-Do List
Tutorials and Details: Dictionaries
, Easy as 1-2-3-4-5
, How-To Examples
, Generators (Prototypes)
, Memory Profile
, Group Descriptions
, Context Menu Example
, Cascading ListBox
, Visual State Manager
Architectural Discussion: Model-View-PresenterRecognitionBEGIN COMPOSITE . . . END COMPOSITE
Below is an example for creating a new composite, adding a new Rectangle to the composite, followed by adding two Textblocks underneath the Rectangle (all in column 0 if using a Grid Composite):
- 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.
.AddText(1,0, "Hello World 1")
.AddText(2,0, "This is text at Row 2 Column 0 in the composite")
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 be associated with such an ID. However, a GUID is not required as one can be created by the library automatically behind the scenes.
This use of ID's works well for binding and retrieving sets of UI Elements. Within a single composite tied to an ID, identify X-Y Coordinates for positioning child elements within a parent container.COMPOSITE STRUCTURE
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?
The different container types are added at the end of a ContentControl. This ContentControl is wrapped in a Border:
, 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.ICOMPOSITE CONTAINER TYPES
Currently, I support multiple containers (each implementing IComposite):
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-columnHorizontalPanel, VerticalPanel, WrapPanel, UniformGrid;
x is ignored (should be 0), y maps to index of ChildrenDockPanel:
x maps to the Dock enum by int: Left = 0, Top = 1, Right = 2, Bottom = 3; y maps to index of ChildrenContentControlPanel:
there is only one x-y and that is 0,0 for the single ChildCanvas:
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.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:26 IPARENT CONTROLS
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 new custom controls.
This humble start has grown into fair support for 26 IParent controls:Code ExamplesListBox ExampleGrid ExampleDock Panel ExampleCombo ExampleMenu ExampleTree View ExampleExpanderListView ExampleButton ExampleDataGridSupported Controls
These controls are official IParents. 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
offered open-source (https://wpftoolkit.codeplex.com/
by Xceed http://xceed.com2. 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 MultiLineTextEditor5. System.Windows.Controls.TextBox6. System.Windows.Controls.DatePicker7. System.Windows.Forms.DataVisualization.Charting.ChartCaveats
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, 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!