Preface and Thanks

This is the final part to my WPF for Beginners series, and it has been quite a journey even for me. It has taken quite a lot of effort to create this series. And I could not have done it without a few people's help, namely the following

Robert Ranck: For creating the VB.NET conversions of my C# projects for all of Part 1 - Part 6 articles that make up this series.

Introduction

I have been working on this app on and off since Part 1, and it has kind of become a labour of love. I wanted to tweak this and that. I am finally happy with it, and I really hope you lot like it as much as I do. I have tried really hard to make it use all the stuff I have covered as part of this article series, which is no mean feat let me tell you. On top of that, I wanted to make it look cool... as I like cool things. So naturally, I went for some Physics driven application. Neato!!!

As I say, this article is the last part (the finale app if you like) where I will be using all the stuff we have learnt along the way. Just to remind you, that means we will be covering all of the following:

This article is actually a sort of joint venture (my first, but hopefully not last one) with my old team leader. Ladies and gentlemen, may I present Mr. Fredrik Bornander. Fredrik is not only the best programmer I have ever met, but he is a very cool guy, whom I really get on with. I also enjoy bouncing ideas of him. We have plans for many, many more articles in this and other areas, so watch out for them.

However, we are where we are, so I think the way I am going to do this article is talk about what the app does, give you a video, and then break it down (basically dissect it) and relate each part of the dissected app to one of the original article series parts. That way, you can see which of this article series you need to read if you want to see how something works in more detail.

As this is a joint article, where Fredrik also created some of the application's code, I will mention what Fredrik did as well. In fact, I am going to get Fredrik to write the words for his part. Of course, as Fredrik is Swedish, his spelling will need to checked (actually for anyone that's read any of my articles, it's probably the other way round.. he should probably check my spelling...though at least I can say "vowels" not "whales" hey Fredrik...ha ha).

One thing that I need to mention is that for this one, there will be no VB.NET version published. It's too much work, and I need to move my attention on to other articles now. Sorry!

Anyway, here is what we are going to cover in this article, but only in C#, sorry again:

Essentially, the demo app is very simple. It uses the standard SQL Server Northindwind database, where a number of Customer objects are first retrieved, and then when requested, a Customer's related Order objects are fetched from the database. Both the Customer and Order objects allow the user to edit their details and have some validation performed to ensure that the entered data is valid. That's pretty much it. But, as we will see, this still has plenty of scope to use all the WPF goodness we have learnt along the way. As I say, we will also mix it up with a pinch of Physics to make it move in weird ways... which we like.

As previously stated, the demo app uses SQL Server (I use SQL Server 2005), but as long as you have the Northwind database installed, it should all be OK whatever version of SQL Server you use. If you don't have the Northwind database, you will need to download and install it from here. Also note that you will need to modify the connection string that the application uses to match your own SQL Server installation. This can be done within the associated app.config file within the "PhysicsHost" project.

I created the entire application and ported Fredrik's Physics code to WPF. It was WinForms based, so Sacha created the necessary changes to it in order to WPF-ify it. But I can't really take much credit for the Physics code. That's Fredrik's baby all the way. Fredrik is really a frustrated games programmer who starts N-many DirectX games a month, but finishes none of them. Ha ha. At least he'll finish this article with me. So yeah... I ported the Physics code to WPF, but also did all the other WPF elements that make up this demo application. This includes Layout/Resources/Commands and Events/DPs/DataBinding/Styles and Templates, and also LINQ to SQL. Oh, and I also created the trivial DashedOutlineCanvas within the Physics project.

Sacha used to work with Fredrik, and a while back at work, Fredrik started working on this Physics thing (whilst he should have been doing what he was paid to do, which is write boring Sybian C++, but hey), which kind of peaked Sacha's interest. This Physics thing that Fredrik was working on later became this CodeProject article. But Sacha thought this could be used within a WPF app, so Sacha and Fredrik set about making that happen. As a result, the Physics stuff you see in this application is based on the original Physics stuff that Fredrik did for his original CodeProject article. Nice one Fredrik.

Due to the nature of Physics, the only way that I can do the attached demo application any justice, at all within the scope of this article, is to show you a video which shows it in action. As such, please click on the image below to see a video of the demo application in action:

OK, now I have told you what the app does, told you what you need to try it at home, and shown you a video of the demo app in action. I will not talk you through how it was made. Like I say, I think the best way is to dissect the app and relate it back to the individual articles so that if you are lost or maybe are new to this series, you can go back and have a look at the relevant article part.

The application is structured using two projects: the Physics engine and the WPF application. This is shown below:

These two projects will be discussed in detail below. The WPF project has subfolders which contain various files; the folder name gives you an idea of what the files are for.

This section was written by Fredrik Bornander and proof read and inserted/added to by Sacha Barber.

By using simple Physics to layout controls on a panel, it is easy to get an application to have a very different feel than applications using "normal", static layout of its controls.

The aim with this Physics implementation is to create an easy way for developers without any experience in Physics programming to be able to build cool looking applications.

By creating a control, in this case, a subclass of Canvas (which is called ParticleCanvas) that can be used as any other control in a window, it's simple to add Physics controlled controls to any UI.

Any control added to ParticleCanvas can then be related to a Physics Particle; Springs are then added to constrain the particles in whatever configuration is desired. It should be noted that the controls should really only be added to the ParticleCanvas in the code-behind where they are allocated to a Particle and attached to a Spring. If they are added in XAML, there would still need to be some code added in the code-behind to attach the controls to Particles.

ParticleCanvas Class

ParticleCanvas is the canvas control that owns ParticleSystem (Physics system) It uses a DispatcherTimer to regularly update the state of its internal ParticleSystem (Physics system) so that it can be animated. It does this by telling the internal ParticleSystem (Physics system) to do an integration using the elapsed time; an integration is the operation in which the ParticleSystems (Physics system) next state is computed. This is done once for every timer "tick", and after each integration, all the controls that are related to a Physics Particle are relocated to the Particle's new position. This is all taken care of in the HandleWorldTimerTick method:

///<summary>/// This method is hooked to a timer event and is responsible for calling
/// the methods that updates the world state.
///</summary>privatevoid HandleWorldTimerTick(object sender, EventArgs e)
{
Rect constaintsRectancle =
new Rect(0, 0, this.ActualWidth, this.ActualHeight);
lock (ParticleSystem.Particles)
{
// TODO: Make sure the actual timestep is configurable, // or better yet, is the actual time elapsed between updates.
ParticleSystem.DoEulerStep(0.005f, constaintsRectancle);
foreach (Particle particle in ParticleSystem.Particles)
{
// Make sure the Controls are located center on their particles.
particle.SnapControl();
}
}
this.InvalidateVisual();
}

The final call to this.InvalidateVisual() forces ParticleCanvas to redraw its controls, which snaps the Particles to their new positions.

As the user is able to drag Phyics constrained controls around using the mouse, ParticleCanvas has to keep track of a series of mouse events.

PreviewMouseDown, PreviewMouseMove, and PreviewMouseUp are all used to handle control dragging.

During PreviewMouseDown, the list of Physics Particles are queried for a Particle with the event sender control related to it; i.e., a search is done to see if there is a Physics Particle that is currently related to the control that received the mouse event. If this is the case, that control is brought forward along the Z-Index to make it appear on top of other controls, and the related Physics Particle gets its current velocity cleared and its mass set to positive infinity. The reason for resetting the mass is that Particles with an infinite mass is ignored by the ParticleSystem (Physics system) when the integration is done, and this is important as only the mouse should control the movement of that Particle now.

///<summary>/// When the mouse is clicked on a control in the Simulation panel all
/// Particles are searched to find the Particle that has the Control
/// as associated control. Then that Particle is made immovable by setting
/// its mass to infinity and are thus no longer effected by the simulation.
/// Search for control has to go up through the tree as only the top level
/// control is associated with the Particle if a particles associated
/// Control is a Panel containing more controls.
///</summary>publicvoid ParticleCanvas_PreviewMouseDown(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && ownerWindow != null)
{
previousAbsoluteMousePosition = Mouse.GetPosition(this);
Vector mousePosition = previousAbsoluteMousePosition.ToVector();
var particleWhere = from particle in ParticleSystem.Particles
where particle.Control == sender
select particle;
if (particleWhere.Count() >0)
{
Particle particle = particleWhere.First();
if (selectedParticle != null)
selectedParticle.Mass = selectedParticleMass;
selectedParticleMass = particle.Mass;
selectedParticle = particle;
selectedParticle.Mass = Single.PositiveInfinity;
selectedParticle.Velocity = new Vector();
selectedParticle.Control.SetValue(Canvas.ZIndexProperty, zIndex++);
return;
}
}
}

During PreviewMouseMove, the distance the mouse cursor has travelled is measured, and the Particle is updated with the same movement; the control itself will have its position updated automatically by the next timer tick.

///<summary>/// This updates a Particles position when a Control is being dragged.
/// Note that it is not required to move the Control as this is being
/// fixed in HandleWorldTimerTick when Controls snap to Particles
/// positions.
///</summary>publicvoid ParticleCanvas_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if (selectedParticle != null)
{
Point absolutePosition = Mouse.GetPosition(this);
Rect constaintsRectancle =
new Rect(0, 0, this.ActualWidth, this.ActualHeight);
selectedParticle.SetPosition(
new Vector(
selectedParticle.Position.X +
(absolutePosition.X - previousAbsoluteMousePosition.X),
selectedParticle.Position.Y +
(absolutePosition.Y - previousAbsoluteMousePosition.Y)),
constaintsRectancle
);
previousAbsoluteMousePosition = absolutePosition;
}
}
}

When the mouse is released and the PreviewMouseUp event fires, the Particle's original mass is restored; this will (if the original mass wasn't positive infinity) allow the ParticleSystem (Physics system) to again move the particle (and therefore also its related control) around.

The ParticleCanvas also (optionally) keeps track when the window it is contained in is being moved so that the Particles can be updated accordingly; this allows for a natural behaviour of the controls suspended by Springs as they'll swing back to their state of rest. The ParticleCanvas does this by moving all the movable (those with mass not equal to positive infinity) Particles by the negative distance the window just moved.

This means that if the window was dragged ten pixels to the left, the Particles would be relocated 10 pixels to the right. Try it for yourself; it looks quite cool.

ParticleSystem Class

The ParticleCanvas' internal Physics simulation is maintained by a ParticleSystem instance. The ParticleSystem is a class which owns all Particles and Springs, holds all world properties (such as gravity and drag), and computes the integration. The integration is calculated in two major steps:

Step 1: Calculate the Derivatives for All Particles

This means calculating the difference in velocity and position, which is acceleration and velocity. First, all existing forces that are currently acting upon a Particle are cleared so that the Particle is completely unaffected by force. Then the "world" forces are applied; this is the force of gravity and the drag which is kind of like wind resistance. The drag is important to simple simulations as this one, as it puts a "damper" on the system which stabilizes it. After that, the forces that the Springs add to the Particles are applied to the Particles, and after that, the just calculated "state" is stored away in the Particle as a ParticleState.

Step 2: Update the Position with the Particle State

First, the Particle state is scaled down by the time factor so that the update will be proportional to the time elapsed. After that, the Particle velocity is updated by simply adding the state velocity to the Particle's current velocity. The same normally applies for position as well, but as the Particles can be constrained to the ParticleCanvas's rectangle, a few calculations have to be done to make sure it bounces off the edges if it is moving off the screen.

Particle Class

The ParticleSystem class is responsible for calculating positions and velocities of Particles. Particles are rather simple classes that hold position, velocity, force, and mass used when doing the simulation, and also, optionally, a relation to a Control. If a Control is related to a Particle, that Control's position is aligned with the Particle when the method SnapControl is called.

Other than that, the Particle doesn't hold much logic; it's all calculated by the ParticleSystem class. If a Particle is assigned a mass of positive infinity, it is not affected by any force; this is useful when creating anchor points in the simulation. Note that even if the Particle has positive infinity mass, it can still be moved by dragging it with the mouse.

Spring Class

Springs are used to constrain two Particles by applying a force to the Particles so that the Spring's properties are satisfied. The properties of the Spring are:

Rest length: This is the distance the spring will eventually end up in if the Particles are affected by no other forces.

Spring constant: This is a measure of how stiff the Spring is; the higher the value, the more "eager" to reach its Rest length.

Damping constant: This is a damper that is used to make the Spring move slower and stabilize the simulation.

The forces that the Spring applies to its two Particles are calculated by a method that might look a bit complicated, but really is quite simple:

Calculate the direction the force should have, this is always in the direction of the other Particle; apply the Spring constant to the difference in distance between Particles and the desired distance. Figure out the amount of damping needed, this is relative to how much or how little the Particles are moving away from each other; the more they're moving away, the more the damping. Calculate the force to apply to the first particle, negate the force, and apply it to the second Particle.

The Spring can also render itself using a ISpringRenderer; this is just a way to get different looks for a Spring.

Layout is literally used everywhere within the demo app. From the Windows to the UserControls to the Custom Styles/Templates. It's everywhere. Probably the best way is to pick a couple of Windows and provide screenshots and the associated layout markup that creates the Windows. Though, there are far too many areas where Layout is used to go into everything. But this should give you a good idea.

There are four Windows within the demo app:

And there are two User Controls, though I won't discuss the layout for these just yet, as the discussion about the UserControls is more suited to Templates/Styles and Lookless controls.

If we pick on two or three of these Windows, say the following ones, we should be able to discuss enough layout I think:

MainWindow.xaml

EditOrderWindow.xaml

AboutWindow.xaml

OK, so MainWindow.xaml looks like:

Now we will forget about the ParticleCanvas in the middle (the yellow boxed area) just for a moment, as Fredrik should have talked about this a bit in the Physics section, and I will talk about the layout aspects a bit more below. Once we gloss over the ParticleCanvas, the layout is failry trivial (I have removed some markup for clarity).

Here is the layout for this Window (again, I've removed certain markup for clarity):

<Windowx:Class="PhysicsHost.AboutWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:PhysicsHost"local:GlassEffect.IsEnabled="true"Title="Particles"Icon="../Images/logo.png"ResizeMode="NoResize"Width="500"Height="350"Background="#FF000000"><Window.Resources><Storyboardx:Key="OnMouseEnterSachas">
....
....
</Storyboard><Storyboardx:Key="OnMouseEnterFredriks">
....
....
</Storyboard></Window.Resources><Window.Triggers>
....
....
</Window.Triggers><!-- START OF LAYOUT --><DockPanelWidth="Auto"Height="Auto"LastChildFill="True"Background="#FF000000"><CanvasWidth="Auto"Height="49"Background="#FFFF9900"DockPanel.Dock="Top"><ImageWidth="200"Height="50"Source="../Images/aboutHeader.png"/></Canvas><GridWidth="Auto"Height="Auto"Background="#FF000000"DockPanel.Dock="Top"><Grid.RowDefinitions><RowDefinitionHeight="25"/><RowDefinitionHeight="*"/></Grid.RowDefinitions><CanvasGrid.Row="0"Grid.Column="0"Width="Auto"Background="White"HorizontalAlignment="Stretch"VerticalAlignment="Top"Height="25"><Pathx:Name="pthSachas"Fill="Black"Stretch="Fill"Stroke="Black"Width="10"Height="10"Data="M0,0 L 0,10 L 5,5"Canvas.Left="20"Canvas.Top="8"Visibility="Visible"/><Labelx:Name="lblSachasBit"Width="133"Height="auto"FontFamily="Aharoni"Foreground="Black"Canvas.Left="31"Content="What Sacha did"Canvas.Top="4"/><Pathx:Name="pthFredriks"Fill="Black"Stretch="Fill"Stroke="Black"Width="10"Height="10"Data="M0,0 L 0,10 L 5,5"Canvas.Left="239"Canvas.Top="8"Visibility="Hidden"/><Labelx:Name="lblFredriksBit"Width="133"Height="auto"FontFamily="Aharoni"Foreground="Black"Canvas.Left="250"Content="What Fredrik did"Canvas.Top="4"/></Canvas><CanvasGrid.Row="1"Grid.Column="0"><!-- Sachas bit words --><TextBlockx:Name="tbSachas"Width="215"Text="Sacha is responsible for converting
Fredriks Physics classes from a Winforms
environment into WPF. Sacha also created
this application, and the underlying classes
that support the application. Fredrik
and Sacha used to work together. Fredrik was
Sachas team leader. Sacha really wants
Fredrik to come and work at Sachas new job,
where they can share their love
of http://icanhascheezburger.com/"TextWrapping="Wrap"RenderTransformOrigin="0.5,0.5"Background="Black"Canvas.Left="16"Foreground="#FFFFFFFF"HorizontalAlignment="Left"Height="180"VerticalAlignment="Stretch"Canvas.Top="0"><TextBlock.RenderTransform><TransformGroup><ScaleTransformScaleX="1"ScaleY="1"/><SkewTransformAngleX="0"AngleY="0"/><RotateTransformAngle="0"/><TranslateTransformX="0"Y="23"/></TransformGroup></TextBlock.RenderTransform></TextBlock><!-- Fredriks bit words --><TextBlockx:Name="tbFredriks"Width="215"Text="Fredrik is a Swedish chap that knows what's what when
it comes to programming. He used to be Sachas team leader,
but Sacha had to leave to pursue his WPF interest.
Fredrik can program anything (apart from WPF),
but is most happy writing games in
DirectX that he never finishes. He wrote the original
Physics for this application. Basically he's smart.
The best you'll ever meet. I once saw him write a 3D screen saver
in about 2 hours without needing to look anything up. He rocks"TextWrapping="Wrap"RenderTransformOrigin="0.5,0.5"Background="Black"Canvas.Left="250"Foreground="#FFFFFFFF"HorizontalAlignment="Left"Height="1"VerticalAlignment="Stretch"Canvas.Top="0"><TextBlock.RenderTransform><TransformGroup><ScaleTransformScaleX="1"ScaleY="1"/><SkewTransformAngleX="0"AngleY="0"/><RotateTransformAngle="0"/><TranslateTransformX="0"Y="23"/></TransformGroup></TextBlock.RenderTransform></TextBlock></Canvas></Grid></DockPanel></Window>

ParticleCanvas - Advanced Layout

As ParticleCanvas inherits from Canvas, several layout oriented overrides must be performed. These are as follows:

ArrangeOverride: When overridden in a derived class, positions child elements and determines a size for a FrameworkElement derived class.

MeasureOverride: When overridden in a derived class, measures the size in layout required for child elements and determines a size for the FrameworkElement-derived class.

As with Layout, the demo app uses resources all over the place. Though, one thing I should point out is that they are all static resources. There are none that change once assigned, so there is no need for any DynamicResource allocation. I have partitioned most resources (there are still a few Window level resources around) into three files, as follows:

StylesAndTemplatesCommon.xaml: Used by 1 or 2 common areas

StylesAndTemplatesGlobal.xaml: Used by most demo application items

StylesAndTemplatesValidation.xaml: Used for data validation purposes

Just to remind ourselves of how to use resources: we start by declaring a resource dictionary. Let's take the the StylesAndTemplatesValidation.xaml resource dictionary as an example.

Then in the area where we want to use this resource, say on EditCustomWindow.xaml (where databinding is used), we simply need to reference the Resource Dictionary. I am using a MergedDictionary, but there are other ways (like code). Let's see:

We can see that there is a MergedDictionary declared on the EditCustomWindow Window, and that there is a TextBox on this Window that uses a StaticResource called "validationStyleTextBox" which is using the resource whose Key is "validationStyleTextBox" from within the resource file that has been referenced through the use of the MergedDictionary. This resource "validationStyleTextBox" is contained within the StylesAndTemplatesValidation.xaml resource dictionary.

This is typically how the demo app is using resources. Though, there are occasions where I am using local Window or Control level resources, which don't use MergedDictionarys. These are declared as follows:

You can refer to Part 3 for more information about Commands and Events in WPF.

The demo application uses three Routed Commands, which are as follows:

CustomerViewModel -> ShowHideOrdersForCustomerCommand, for viewing the Orders for a specific Customer

CustomerViewModel -> SubmitChangesCommand, for saving a single Customer

OrderViewModel -> SubmitChangesCommand, for saving a single Order

The demo application uses the ModelView-ViewModel (MVVM) pattern, so these commands and how they tie up with the overall architecture will be mentioned a bit more in the Databinding section of this article. But for now, let's just concentrate on how the commands are defined and used.

The reason that Routed Commands are good is that we can have a layer of abstraction between the UI and where the command is actually declared. Of course, sometimes it is convenient and necessary to have the command declared/bound and executed all within the main UI; however, it is better to have some level of code separation. By separating the command from the UI, we can offer the potential for the UI VisualTree to be replaced. And as long as the new UI VisualTree contains the relevant command bindings, the application will still work. Josh Smith refers to this as structural skinning in his podder article series. Have a look. You'll see what I mean.

But anyway, back to the commands that this demo app declares. Let's look at them one by one.

CustomerViewModel: ShowHideOrdersForCustomerCommand

There is a command that is created within CustomerViewModel.cs that has its command CanExecute/Executed bindings set in the MainWindow file. The actual UIElement that triggers the Command is used on the PART_SHowHideOrders button within the CustomerUserControl. As the CustomerUserControls are generated within the MainWindow window, the correct command bindings exist, so when the button is pressed on the CustomerUserControl button, due to the routed nature of Routed Commands, the notification flows back to the MainWindow file which runs the Executed method, which was set within the MainWindow command bindings.

So we have some code to declare the command within the CustomerViewModel.cs file.

And then we have a StaticResource which provides a default Style for the CustomerUserControl which contains the PART_SHowHideOrders button which uses this command. The command is actually set in code. This is shown below. I have removed anything that is not required to illustrate this point.

This is the code-behind that sets the PART_SHowHideOrders button command. By doing this in code behind, we are allowing the control to be lookless, where the end user can totally restyle the control. But we will talk more about this later in the Styles/Templates/Lookless Controls section.

This command actually checks whether the current Customer (LINQ to SQL object, more on this later) associated with CustomerUserControl.xaml has enough Orders. If it does, the Show Orders button will be allowed to run; otherwise, it won't. See the button grayed out in one of the CustomerUserControls below.

When the command is run N-many (configurable in App.cs) Orders associated with it are added to ParticleCanvas as new Particles.

So that's how that command works.

CustomerViewModel: SubmitChangesCommand

There is also another command that is declared within the CustomerViewModel.cs that has its command CanExecute binding set to be always true within the actual CustomerViewModel.cs file and the Executed bindings set within the EditCustomerWindow.xaml window.

Let's see how this command is declared and has its CanExecute binding to return true constantly. This is shown below, and is within the CustomerViewModel.cs file.

What is happening here is, within the CustomerViewModel.cs file, the command is declared and is set to always be enabled. And the Executed command binding method simply updates the bound Customer (LINQ to SQL, more on this later) object. And that's it for this command.

OrderViewModel: SubmitChangesCommand

Works in the same manner as the CustomerViewModel SubmitChangesCommand command, but is used for saving Order objects instead of Customer objects.

I didn't really have a cool idea about how to use DPs or Attached Properties for this article. So I did what any resourceful developer should do... steal some code, but quote the original source. To this end, I am using the code as posted by CodeProject user Rudi Grobler. Rudi's code uses Attached Properties (my favourite of all the DP family) to extend glass into your Window (which happens in Vista, by default) using P/Invoke. This technique is in a every WPF book out there, but the use of the Attached Property is the bit I like. And that is what Rudi did, so that's why I am using it.

Let's see how we do this. I have posted Rudi's original code here (I have just renamed the namespace). But you can get the full brief at his original article post, which is right here.

The important part is this class which provides the Attached Property and the P/Invoke stuff:

You can refer to Part 5 for more information about DataBinding in WPF.

This is perhaps the most complicated part of the demo application. The reason that it's complicated is as follows:

The demo app is using LINQ to SQL for the database interaction

The demo app is using an N-Tier approach to working with the database

The demo app is using validation through the .NET 3.5 IDataErrorInfo interface

The demo app is using manually updatable bindings (which was not discussed in Part 5)

As you can see, there is a fair bit to talk about just on this one subject. I think the best bet is to tackle this one thing at a time, in the order described above.

LINQ to SQL

As I am using SQL Server and VS2008, why not use LINQ to SQL I thought. So that's exactly what I dis. I used two tables, Customers/Orders, from the Northwind database. I just dragged these two tables onto the LINQ to SQL Designer.

This is all very standard stuff. This LINQ to SQL designer creates the file Northwind.Designer.cs which holds all the table mapping and objects required to communicate with these two Northwind tables. This class creates the NorthwindDataContext, which is the main object that should be used to query/update the database against. As I say, this is all very standard.

The only issue was that I wanted to only have one instance of NorthwindDataContext in the demo app. Luckily, due to the wonderful Partial Class feature, it was trivial to just create another partial class which provides the singleton instance for NorthwindDataContext. This is shown below:

N-Tier approach

I wanted to make the demo application as easy to understand as I could, and I think a major part of this is structure. As such, the demo application uses an N-tier approach where the data flow is something like in the following diagram:

Where MainWindow uses the CustomerViewModel to fetch a number of Customer objects which are then used as DataContext values for individual CustomerUserControl objects. The Customer objects are supplied by calling the CustomerBAL object, which in turn gets the required Customers from the actual Northwind database by using the NorthwindDataContext.

This may be a little clearer if we look at the code.

Starting at the top where the individual CustomerUserControl objects are created, this is done within the MainWindow.Xaml.cs file.

This class is responsible for not only interacting with the NorthwindDataContext, but also for running the business rules. In this case, the rules are very simple, does the customer has at least one associated Order.

The final layer is the NorthwindDataContext which, as I stated earlier, is standard LINQ to SQL generated code.

IDataErrorInfo Interface Validation

As we are dealing with bound data, when we edit either a Customer or Order object, we must ensure that there is a way to validate the data entered. I have chosen to use the new .NET 3.5 method which is by the use of the IDataErrorInfo interface.

This interface must be used on the binding source object. In the demo app's case, this is either a Customer or a Order object coming from the auto generated LINQ to SQL code. When I first thought about this, I though this could be quite a pain as I would have to manually change auto generated classes. As luck would have it, Partial Classes to the rescue again. Looking at the auto generated stuff LINQ to SQL produces, say for Customer, we can see the following:

Not only is the class partial (which means we can extend it in a different source code file... one of the best things MSFT ever did are Partial Classes), but the LINQ to SQL Designer makes all the generated classes implement the INotifyPropertyChanged interface. Which is a must when dealing with WPF. This is excellent news. All that had to be done was to create an extra Partial Class for Customer and one for Order. This is shown below for Customer:

And now, we have all the bits we need to be able to perform validation using the information provided by the use of the IDataErrorInfo interface. Basically, what we do is associate a Style with a TextBox which uses the error message generated by the IDataErrorInfo interface implementation. This Style is described a bit more below.

Manually Updatable Bindings

One of the things that I wanted was the ability for a user to be able to either update a bound field or to cancel the edit entirely. Within WPF, this is pretty easy to do; you just need to need to set the UpdateSourceTrigger property of the binding to Explicit. And then, you have to manually update the binding yourself in code. If we stick to just examining how the Customer object works, the same is true for Order objects.

There is a Window (EditCustomerWindw) for editing a single instance of a Customer object. Basically, the DataContext of the EditCustomerWindw is set to a single Customer object, and then the EditCustomerWindw has various markup that binds to this single Customer object. But all updating to the bindings are set such that their UpdateSourceTrigger properties are set to Explicit. So there is some code that has to be done to update the underlying object from the bound values.

Notice the use of the <validation:ErrorProvider x:Name="errorProvider"> element. This is a special element that I use to wrap my manually updatable bindings. As I am not setting the validation rules in the XAML and manually updating the bindings, I needed a way to create the validation rules at the point where the user chose to update the underlying data source. Basically, clicking the Save button. What this class does is use Reflection to get a list of the objects that have bindings, then get the DPs that it needs to use to update the bindings with, and then creates the appropriate validation rules for the bindings. It's cool. This comes from another MSFT MVP called Paul Stovell, and can be found right here.

Here is the relevant code for the validate() method. Notice the use of the IDataErrorInfo that was discussed earlier. See how it's all starting to fit together.

Lookless Controls

Recall in Part 6, I had a section about lookless controls. For those that haven't read that section, it's basically like this. Using Styles/Templates, a designer/developer is able to totally swap out the entire visual tree for a class. For example, I could have a UserControl that I want to contain a button and a listbox. But the designer or another programmer decides to create a new Style for my UserControl that doesn't provide a button or a listbox.

How can we cope with that? Well, what we can do is decorate our objects with the PartTempateAttribue to relay our intentions of what the control should contain within its visual tree in order for it to work correctly. And we can also check for the existence of the required visual elements that are required in order for the templated control to work.

This is what is done within the demo app for both CustomerUserControl and the OrderUserControl. Let's have a look at these, shall we?

CustomerUserControl

The CustomerUserControl looks like this by default:

Now, this is down to a default Style that I created, which tells the control what it's visual tree should be. This default Style is shown below:

Notice at the top of the class, I use the PartTempateAttribue to relay my intentions of what elements were expected and what they should be called and what type of elements are expected.

The other thing to note is the OnApplyTemplate() method, which is where the expected elements are looked for, and if found, have their required events wired up.

In the above example, I am also using a Command which is assigned to one of the expected buttons ("PART_ShowHideOrders"). The usage of Commands within the demo app was discussed in the Commands and Events section.

OrderUserControl

OrderUserControl looks like this by default, and works in a very simliar manner to that described above:

Various sources were used along the way; these were all included in the individual articles, so you should use those for a list of resources that pertain to the individual subject of the separate article. Links to the previous articles are here:

21 Feb 2014: Best VB.NET Article of January 2014 - Second Prize
18 Oct 2013: Best VB.NET article of September 2013
23 Jun 2012: Best C++ article of May 2012
20 Apr 2012: Best VB.NET article of March 2012
22 Feb 2010: Best overall article of January 2010
22 Feb 2010: Best C# article of January 2010

I have started to read this article and it looks like a very good one.
But I have a problem to launch the demo application. I have installed the Northwind thing as you mentioned to do but when I start the application, I got an error message saying me that it's impossible to established a connection with the Northwind database.

I have change the connection string in app.config by tipping my computer name instead of VISTA01 but it seems that it's not sufficient. What can be the problem ?

Since it's running a (simplified) physics simulation it's always animating, regardless if all items on screen have stopped moving.

Still, it's using up way more CPU than it should and that's because the simulation time step is oversampled. You can play around with the timer frequency and the physics delta time to fix it , both can be found in ParticleSystem.
If I use ParticleSystem.DoEulerStep(0.07f, constaintsRectancle); and worldTimer.Interval = new TimeSpan(0, 0, 0, 0, 50); it seems to lower the CPU usage considerable (although increasing the step time will make the simulation more unstable).

What I like about this article is how you used MVVM. I am really impressed by this new pattern. Separation of View and ViewModel makes the whole process so much easier for both Designer and Developer. Just like in your demo here, it doesn't matter how complex your view gets, there are no additional burden for the developer. Developer takes care of the ViewModel and the Designer is happy! I look forward to start using MVVM at work. Thanks.