Standardizing the development of custom controls
Over the past couple of months I got many opportunities to develop a variety of custom controls for WPF. Some of them are as basic as a Numeric TextBox and some are as complex as ElementFlow. It is interesting how many times the same set of patterns repeat themselves again and again. In this post I want to share a few ideas related to standardization of custom control development. I believe that such a thinking process could simplify creation of new custom controls.
Thinking in Tracks
A custom control is a combination of many features, each of which can be uniquely identified. I call each such feature a Track. Each track is theoretically orthogonal to other tracks but also has an ability to communicate through a defined interface and storage. You can think of tracks also as tracks from a song composition. A song consists of many audio + instrument tracks. Each of them are unique in themselves but also vary their tempo, volume, etc at different points in the song. Below is a simple depiction of tracks from the Mac OSX’s GarageBand application. The final song output is a combination / blend of these tracks.
Tracks in a custom control
A custom control is also made up of a variety of feature-tracks. From my past experiences I have compiled the following set of possible tracks:
- Type: whether its a singular control like Button, list-based control like ListBox or hierarchical control like Tree
- Selection: selections (single, multi) on list or hierarchical controls
- Layout: layout of items in list or hierarchical controls
- Hover: mouse hovers
- Animation: for animating state changes
- Virtualization: for handling large data-sets in list / hierarchical controls
- Data: relates to data-binding
- Rendering: the visual tree of the control
[Note that the tracks are pretty much pre-defined and well-known. I may have missed a track or two, but the general idea is that these tracks are all you need to create a broad range of controls.]
You have the flexibility to either include a track or totally skip it. Also a track could be added at anytime during the life of the control. In other words you can influence the behavior of a control by varying its tracks. You can create a new control by just combining a bunch of tracks that are relevant to that control. It is possible to create a repository of implementations for standard tracks, which can be used directly by new custom controls.
Many of these features are already provided by WPF. The point I want to make is that custom control development should become an act of combining the relevant tracks (and fine-tuning) than building these features by hand each time. Something like so:
1 CustomControl control = new CustomControl(); 2 control.Tracks.Add(new ListTypeTrack()); 3 control.Tracks.Add(new SelectionTrack()); 4 control.Tracks.Add(new HoverTrack()); 5 control.Tracks.Add(new VirtualizationTrack()); 6 7 dockPanel.Children.Add(control); 8
I don’t have working code that does all of the above but in my most recent custom controls I have started adopting this technique. I am still far away from the picture I have drawn above. Also you may have noticed that I skipped talking about interactions between tracks. I will do that in a different post. I am certainly seeing a lot of benefits in this approach and moving forward this is probably how I will be developing controls.
Feel free to bug me for questions or comments.