Categories: .Net, C#, WPF
Posted by
mheydt on
3/16/2008 4:41 PM |
Comments (0)
During the process of learning how to do "real things" with WPF, one of the major issues that I came across as I think it is not documented fairly well is how to create a user control that displays multiple items (and without being a ItemsListControl) that have a default look, but which allows the user to completely change the way in which those items render themselves.
The example I will use is of a force directed layout control that I have been developing. For the unititiated, a force directed layout control using springs takes a network of items and repositions them in an order that is visually aesthetic and where each node is positioned as though it is "forced" away from neighbor nodes by "springs."
As an example, here is the control I am building in action. This picture is the network with nodes randomly place in space prior to layout (nodes are positioned randomly in code behind):

In this app, pressing a key causes the force layout engine to reposition the nodes to look as follows:

The process of force directed layout is not the topic of this post, but how to write your control to allow the user to change the look of controls used by your control without changing code.
To start this explanation, let me exhibit the XAML used by this control:

There isn't a whole lot to this control as the actual creation of nodes and lines is done in the code behind. The important part is that the templete for the node and lines between the nodes are defined as ControlTemplate's and stored as a resource in the control. The code behind will then dynamically load the control template when needed and use it to create an actual WPF control that is set to be a Child element of the Canvas.
To create an actual WPF control from a ControlTemplate stored as a resource and add it as a Child of the canvas is fairly easy as it only requires a few lines of code:

So, whenever a node is needed in the graph, this code will create one of the teal balls and place it on the canvas.
Now, say that I have packaged this control as a DLL and redistribute it, but I want to allow the user of the control to be able to use a different element for a node instead of the default teal ball. What needs to be done to support this is to add a DependencyProperty to the control that allows the person using the control to specify the key of their own control template to use, and to also change the code snippet above to look for the name of the control through the propery instead of being hard coded.
The DependencyProperty is coded as such:

The declaration of this property allows a user of the control to define a new control template to use for the nodes instead of the default by binding to this property in the XAML of the control client.
For example, this XAML reuses the control and also specifies that the teal balls be replaced with blue rectangles with a black border (and also that the lines be replaced by orange lines):

And the visual result of this is:

Notice that I used data binding to set the NodeControlTemplate property. Because of using data binding (which I highly recommend), the property must be defined as a DependencyProperty instead of a CLR property.
Lessons learned:
If you are compositing a controls visual representation with sub controls that you want to allow users to override the visual representation of those controls:
- Declare those controls as ControlTemplates
- Declare a DependecyProperty of type ControlTemplate to allow the user to override the default ControlTemplate
- Use the ControlTemplate.LoadContent method to create the control and add it as a Child of your canvas.
ca810fba-78f9-43ba-aae2-eb82b1fdce45|0|.0
Categories: .Net, WPF
Posted by
mheydt on
3/15/2008 11:13 PM |
Comments (0)
I've been doing some hardcore WPF coding on the side the last few weeks. This has primarily been an exposition in being able to learn more details while putting together a non-trivial application the includes many features that I see used in many WPF applications including:
- Advanced navigation models
- Various types of animation
- Dynamic rendering
- UI Elements such as carousels, network visualization, animated search
I had a number of "widgets" that I had tinkered with over the last few months, as well as I have done some significant research into available 3rd party controls for WPF, and slapped these together into an application that can show off some of the capabilities.
My first requirement was to provide the GUI with a striking display that makes the application visually "pop", instead of just looking like a regular old GUI. Conceptually, I think of this in context of using an iPhone and how everything is visually stimulating yet at the same time very easy to navigate, but all at the same time being within a common, single, workspace (basically, one window, no dialogs, minimal popups).
After much thought this came around to my wanting the application GUI to have a single and almost unobtrusive menu, and without drop downs, as I don't like them and I think there should be a better way. This menu could be used to select main categories of functionality in an application, and then there should be a different model of showing the the subtasks involved with that menu.
I've also become enthralled with the concept of the "Carousel", something that appears to be new to WPF apps and I think a great new concept for displaying information. Up to now, these carousels have been used to do things like show multiple images, but I think they also will have great value in providing navigation within an application. This I have modeled in this demo app and I will exhibit over a few posts yet upcoming.
While looking around for some things that excited me, I came across the 3dCarousel in the Contoso app. Unfortunately for the life of me I can't find that link to show it, so if know of it let me know and I'll add it. The important thing with this though was that it should what I thought was a fairly nice UI model, with a small menu, tabs to select sub-tasks, and a nice hierarchical carousel (another topic all together).
So I investigated that apps source, and build out a framework on it. I'll be frank here in saying that I didn't like the code much as I thought it had very bad seperation of concerns (every here of a user control?). And the colors were pretty Miami-Vice in nature. So, I built some reusable controls out of it for the UI and make the colors a little more brooding (and retooled it to show my info, not theres).
Here's a quick look:

The things inherent in this display are:
- A nice background giving the app some "pop"
- A small menu that isn't taking up space
- Tabs that allow you to navigate functionality in the selected part of the app
- A slider to change the zoom on the display
- An unobtrusive search box
- An interesting component of application functionality in the window
I want to try and keep these posts to a reasonable size, so I'll stop here for now. In future posts I will elaborate on:
- Just what the heck is that spider web?
- How the background is constructed
- How the tab control is built and operates
- Ditto for the menu
- The carousel I built (not shown yet)
- Animation between parts of the application
- Carousel animation
- Menu -> Tab -> Carousel navigation within an app
- Data binding, and other things too numerous to list right here
Back with more shortly...
8738ee5e-f5ae-44df-96bd-d56c9fb9c5b3|0|.0
You heard it here first.
Extreme Decomposition (XD) is a term that I believe that I coined a few years ago and I've still not seen it used anywhere, so I'm staking my claim to it officially here.
XD is a concept of designing software where functionality is broken down iteratively until it is completely decomposed into "atomic" items that serve a single unit of functionality in a system. Each of these items must be able to be independently coded and tested to be a viable component of a software system.
Through this building of many atomic and properly functioning components to a system, they can then be reliably reused as subcomponents of higher level abstractions in the system, each of which must be individually tested themselves by building new tests that the test both the new functionality that integrates the child components.
Therefore by building a system of atomic components glued together then we can rapidly build new systems that meet the reliability and agility required in todays world.
For more information, please visit
xDecomp.info.
53ee675f-71e3-4a48-8339-9b5ee286b00a|0|.0
Categories: General
Posted by
mheydt on
3/15/2008 10:36 PM |
Comments (0)
If you hadn't noticed, I changed the theme of the blog. This also involved a change of the engine from BlogEngine.NET to DasBlog. I used to use DasBlog years ago, but felt it lacked in features as others were innovating faster. About a 6 months ago I moved over to BlogEngine.NET as I thought it was the most feature capable at the time (I as already not using DasBlog for quite a while). With the use of a Mac as my primary computer, and with trying to find a good blog client, I found that I was experiencing many small problems with BlogEngine.NET, so I looked around and found out that DasBlog had really evolved to appear to be the best self hosted engine available (at least for on .NET servers).
And hence the flip-flop / churn. And I REALLY like this theme.
652c305b-7583-44ad-8cbf-19cf2079e4ad|0|.0
Categories: .Net, C#, WPF
Posted by
mheydt on
3/11/2008 5:17 PM |
Comments (0)
Been doing a little coding tonight and I found myself once again needing to refer to references to figure out how to declare a WPF RoutedEvent. Getting this done is a four step process in your code, each of the steps being fairly boiler plate (and hence I hope they eventually roll this into the language / CLR along with dependency properties):
- Declare a static RoutedEvent field in your class.
- Register the event during the execution of a static constructor for your class.
- Declare and event Property to allow clients to connect / disconnect from the event
- Raise the event at some point(s) in your code.
Step 1 declares the member that defines the event any by which other methods (such as the RaiseEvent method) can refer to the event that you are declaring. This has the following syntax:
private static readonly RoutedEvent _NodeCreatedEvent;This member is static and read only as there only needs to be one instance and its value should not be changed. Basically, this is initialized in step 2 and not changed by your code at any other point in time.
Step 2 initializes the RoutedEvent field. This is done within a static constructor in the class containing the RoutedEvent field:
static ForceDirectedLayoutControl()
{
_NodeCreatedEvent =
EventManager.RegisterRoutedEvent(
"NodeCreated",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(ForceDirectedLayoutControl));
}A static constructor is executed once and only once by the runtime prior to the class being used in any capacity by other objects to initialize static members to non-default values. This is actually a quite nice feature of C# as this was particularly troublesome in C++ programming prior to .NET.
The code in this constructor utilizes the EventManager in WPF to inform it that we want to declare a routed event to be processed by WPF. We give it a string giving the name of the event (which will also show up in XAML intellisense), the routing technique for the event (which I've only used bubble), the type of handler needed for the event (basically defining the signature of the event handling method - which you can see auto generated by the XAML designer), the the type of the class enclosing the event. Once this method is executed, the runtime will then know how to respond to a RaiseEvent method call on a RoutedEvent object in this type of class.
Step 3 is to declare a property that allows the clients to connect / disconnect from the event. Basically, this allows them to become a "observer" as in the observer/subject GoF design pattern:
public event RoutedEventHandler NodeCreated
{
add { AddHandler(_NodeCreatedEvent, value); }
remove { RemoveHandler(_NodeCreatedEvent, value); }
}A bit on naming. I like to name by event field <EventName>Event, and register it as "<EventName>", and provide a Property with the name <EventName>.
With this in place, you now can raise an event in your class. This is done as follows:
RaiseEvent(new RoutedEventArgs(Button.ClickEvent, this));
When this is called, if there are any observers the WPF runtime will bubble up this event args object.
A variation on this pattern is if you want to pass extra data to the observers as the RoutedEventArgs class only has default fields and no custom ones for your use. To pass data up you need just subclass the RoutedEventArgs class, provide your own fields in that class, and replace the new in the RaiseEvent class with an instance of your subclass.
As an example, in this code I actually want anyone interested to be able to pass back to the code raising the event (through the event args object) a UI element to be displayed by this code. To get this done I declare a class as follows:
public class NodeCreatedEventArgs : RoutedEventArgs
{
public INode Node { get; set; }
public UIElement Element { get; set; }
public NodeCreatedEventArgs(RoutedEvent routedEvent) : base(routedEvent)
{
}
}This is a fairly simple extension to the RoutedEventArgs object as it just declares two properties, the Node field (which is a domain object passed to the observer), and the Element field that is passed back from the observer. You need to pass in the routed event and pass it to the base class as this is how the runtime determines which event to route this to.
Note that this assumes that there is only ONE observer, which works in this model. If there is a need for more than one then we would remove the Element field and make it the responsibility of an observer to call back into the subject to pass the Element to it, in which case it would also need the Node so that the subject object could match up the call. And also note that in this case the actual reply should probably only be done by a single observer (it's fine if multiple listen). The point is, this event is intended to be handled by only one observer, and that observer should assign true to the Handled property of the RoutedEventArgs to prevent it from bubbling further.
Now, the RaiseEvent call becomes:
NodeCreatedEventArgs args = new NodeCreatedEventArgs(_NodeCreatedEvent)
{
Node = node
};
RaiseEvent(args);
Notice the use of the new C# object initialize syntax. Those are so nice! Also note the passing in on the constructor of the previously created routed event object. This is how the runtime will know which event to route as you should notice that RaiseEvent does not actually have an event parameter as it is passed in through the event arguments object.
To handle the event, there are ways to do this in XAML and in C#. In this case we'll use XAML:
<l:ForceDirectedLayoutControl x:Name="fdlc" NodeCreated="fdlc_NodeCreated" />Notice now that since we declared that property the XAML picks up on it and we can declare a method to handle it (actually it's generated by the designer automatically) as follows:
private void fdlc_NodeCreated(object sender, RoutedEventArgs e)
{
}
Obviously this method doesn't do a lot for us, so we need to add some code to it:
private void fdlc_NodeCreated(object sender, RoutedEventArgs e)
{
ForceDirectedLayoutControl.NodeCreatedEventArgs ncea =
e as ForceDirectedLayoutControl.NodeCreatedEventArgs;
Ellipse ellipse = new Ellipse();
ellipse.Width = 20;
ellipse.Height = 20;
ellipse.Fill = Brushes.Green;
ncea.Element = ellipse;
e.Handled = true;
}Here I cast the incoming RoutedEventArgs object to the type that is actually being passed so that the new data that is passed can be accessed (Element and Node fields). I create an ellipse that will be displayed by the classes and pass it back in the element field. Lastly, I stop the bubbling of the event. Note that at this point I don't actually use the Node field, but this will in the future be used to make a dynamic decision on what type of UIElement to create.
03835834-23a9-462f-8ac2-86b3d6b57b77|0|.0
Categories: Agile
Posted by
mheydt on
3/11/2008 5:14 PM |
Comments (0)
I found the one of the recent .NET Rocks podcasts to be particularly interesting (show #322). In it Carl and Richard had Stephen Forte on to discuss managing distributed projects, and in particular using Scrum to manage those projects. The thing that I found most interesting was how Stephen had grown this skill almost organically, like myself (and I think anyone), and especially with how much in alignment he was with my opinions on the topic. Given that I felt that it would be good to itemize and summarize some of the main topics in the discussion between these three gentlemen.
1) Software development lends itself well to distribution of tasks.
The question then becomes why distribute your software development? There are a number of reasons, two of which are primary:
- High quality talent is not always local
- Isolation works - can not get "do not disturb" around the office, and this is a real important issue. There are references given that for example one phone call to a developer will make them take 10-15 mins to get back on track
2) How do I mitigate / manage risk in a distributed project?
There are a number of answers to this since there are actually a number of types of risk to mitigate:
- How do I communicate effectively communicate over large distances?
- How do I cope with giving up control (not micromanaging by having to have everyone right there)?
- How can I tell if someone is thrashing from a distance?
Basically, you can and will lose control of developers even if they are colocated. The trick is to be able to identify it, with local or remote staff. Thrashing is when a developer gets stuck and will not ask for help. This can happen even in a cube, and for weeks at a time, so this is not new even with remote staff. The issue is again how to identify it.
The solution to these comes down to using Scrum as your project management methodology, and this will assist in identifying these issues. Through this you gain control over your through empowerment and even if they are not right there.
Which also leads to the question of isn’t it important to have face to face interaction? Well, it is to an extent. As mentioned later it is important to make sure that most people know each other by face having had some type of in person interaction so that you can “see” the person that is remote, meaning that you can get a read on what that person is saying between the lines. Several techniques for how to do this are given later. Also, stress that communications by e-mail for important items is not the most effective means of getting things done. Stress using phone, skype, webcams, or getting in person if possible.
3) Distribute software development leads to greater agility.
This is true when combined with Scrum and short cycles / iterations. Doing this can lead to very quick releases when properly defined. This is actually a large topic to discuss that I will elaborate on independently in another post.
4) Use available tools to assist in managing the distributed agile process.
There are a number of tools available to minimize distance between team members:
- Scrum: Methodology for collaboration and identifying / assigning work.
- TFS / eScrum: Tools for running Scrum in a distribute manner.
- Skype: for communicating amongst the team with low cost.
And make sure that the Scrum Master ensures that everyone uses them and collaborates daily through the daily Scrum.
5) Identifying and addressing “Thrashing” with remote members.
- How can thrashing be identified over Skype? This basically comes down to being able to ask a simple question: “Why are you working for so long on this?” If you then you get a long answer, basically a laundry list of seemingly unrelated statements to the problem at hand, then they have probably tried lots of things except asking for help.
- Also, if you run one week sprints, you don't have to care too much about thrashing as long as the work is done at the end of the sprint. If it is not done at that time, then you are never more then one week behind and you can then identify those people who need help through the lack of a deliverable.
- It is also important to start with several small architectural sprints (and put these in the wiki - my input). These can be used to define a baseline for how the system should be implemented and reviewed against.
6) How to perform Scrums with remote people
- Keep iterations short, perhaps just one to two weeks. This will ensure that thrashing does not exceed more than one iteration.
- Use TFS with eScrum feature to manage the work items in the iteration and allow all remote team members to collaborate.
- Extensively utilize Skype as well as plug-ins for whiteboarding and sharing. Skypecast daily and make sure you go around the horn and use PTI (pardon the interruption - time is up).
- Prevent “hiders” in the Scrums by making sure that ScrumMasters make sure everyone participates.
- Be diligent to make sure that Scrums do not devolve into status meetings; remember that they are for solving issues and giving marching orders.
- What's the effective size of a scrum - 10 people, then do scrum of scrums
7) Team collaboration
What techniques are there to build collaboration amongst the remote workers?
- Kick off the project in person with everyone present no matter the cost as it will be saved later and it will allow distributed people to get to know each other
- Explain the business in the kick off, as developers will need to understand this to work independently, and may also likely take control of business features through the Scrum process
- Get developers to think as a user, having them always think in the frame of reference of a user operating the system.
- Empower the developer to make decisions as it will mitigate thrashing, and make them feel free to ask for input on the next sprint while working on the current one.
8) How to keep remote developers feeling as through they are part of the team?
The problem(s) here are:
- How to keep remote staff happy and motivated
- How to keep remote staff feeling that they are a part of the team
Solutions are:
- Operate with a staff augmentation model
- Engage with local recruiters to find what local talent you can
- Do a staff rotation model, were every person in a particular office should within a 2 year timeframe work in other offices for extended periods (2-4 weeks), and always have one person from every office in another office to build true relationships.
- These techniques will also let you get to know the people so you can understand them in the e-mail
9) How about dealing with the cultural differences?
- It’s Stephen’s opinion that the younger generation is much more liberal and technology has transcended the cultural borders therefore mitigating those issues.
10) In General:
- It seems as scrum master merges with product manager a lot. This is something that I was aware of from experience, but it was nice to hear Stephen express it too.
- Stephen had a great example of how to use current tools to manage a crisis. A remote worker said he had a power outage. Stephen used google earth and local search to find him an Internet cafe to go work at.
- Carl asked if it would be possible to use second life for remote interaction? I kind of like this idea and may look into it.
- Richard feels that he can handle only a maximum of 0.25 interruptions per hour (2 per 8hr work day).
60432142-5494-4e84-afcb-7195abf8d2a4|0|.0
Categories: .Net, WPF
Posted by
mheydt on
3/11/2008 5:08 PM |
Comments (0)
I’m starting to work on a presentation to people where I work about the differences in WPF versus WinForms and ASP.NET. I quick summary yields these which I’ll elaborate on later:
- XAML to declaratively define interfaces and code
- GDI+ Replaced with DirectX
- Vector graphics model based on Direct3D
- Floating point logical pixel system and 32-bit ARGB colors
- All layout is based upon device independent pixel model and units can be spcified in px (1/96/in), in, cm and pt (resolution independence).
- Animation as a first class programming concept
- Attached Properties
- Dependency Properties
- Visual and Logical Trees
- Dynamic 2 Pass layout model
- Layout models like the web but with much more flexibility and control
- Data and Control Templating
- Data binding
- Event routing / bubbling
- Threading/Dispatch model
- Navigation
- XBAP vs EXE vs Navigation models of applications
- Commands
- Rendering Transforms
- Resources
- Styles, Templates, Skins and Themes
- Visuals and shapes
- 3D
- UI Techniques (Carousels, CoverFlow, Virtualization)
Also worthy of noting are:
- Reference declarations in XAML
- Default models of control layout in Grids and Canvases
With .NET 3.5, the following features are new to WPF:
- Firefox support for XBAPs
- Databinding support for LINQ and IDataErrorInfo
- Ability to place interactive controls in a RichTextBox
- Support for 2-D element on 3-D surfaces
- Add-in model for third-party components requiring a limited security context.
Pains in WPF:
- Lack of controls
- Renaming control classes
697814a3-7f21-490f-9f45-ee439853f8f3|0|.0