.net, 3D, Balder, C#

Balder – where is it, and where is it going?

In 2007 I started something called Balder, a 3D engine for the Web using Silverlight. Back then with Silverlight 1.1 Alpha and later 2.0, there really weren’t that many options to make it especially feature rich, nor fast. My first goal when I started this whole thing was basically to achieve 3D rendering on the Web across multiple platforms (Windows + Mac, later Moonlight on Linux) and have a declarative programming model for 3D. This is still the motivation for Balder; to be cross-platform on the Web and be declarative in its nature. I’ve never had the idea of being a 3D engine to compete with the big engines out there that are both free and commercial, this has been partly a research project for me to learn Silverlight properly from the ground up and also maintain a foot within the graphics programming industry which I still hold dear. Even though my day to day job is something completely different these days, I’ve always had side projects that kept me somewhat close to what was happening in the games industry that I left behind some 10 years ago.

Back in 2007 with SL1.1 and 2.0, you basically had to either built on top of the built in primitives, which were super slow or you had to do magic like create yourself a realtime PNG encoder and draw pixels manually with code and then hand over the generated PNG to an Image control inside Silverlight.

With Silverlight 3 came along the WriteableBitmap that enabled to skip the PNG step and Balder started to pick up performance and features were a lot easier to create. This story continued through for Silverlight 4 and Balder has received many a make over of both its rendering pipeline, but also internal architecture while I’ve learnt more and more in-depth of how to do things in the best way inside Silverlight. With the announcement of Silverlight 5 came a long a low level interface for drawing 3D utilizing the GPU sitting inside your graphics adapter. Finally Balder could shine with great performance and still maintain its declarative, Silverlighty way of doing things.

For SL5, that was the gold-plated story – the reality is quite different. Balder needed yet another architectural make-over in order to achieve hardware rendering with Silverlight. The main problem being that rendering now had to be done on a specific rendering event that sits on a completely different thread than the regular UI thread inside Silverlight. This poses quite a few problems when Balder is built to be declarative and have all the binding capabilities that Silverlight offers.

Most of the architectural change has been done – but far from being finished. There are still some holes that needs to be filled internally in Balder that has to do with code-smell basically. At one point in time, development of Balder went forward too fast – and code-quality was during this period suppressed in favor of number of features per day that could be implemented. I know, I’m not proud, but it was the reality for the period that things needed to get done and they needed to be done fast. Another aspect of Balder development has been the lack of being able to properly test things with unit tests all the way. Quite a few times I’ve tried to do the effort to retrofit tests without succeeding all the way. Silverlight is basically too hard to test if you want to be lightweight with your tests. Sure, there are things out there that mock out the runtime and you can make most of your code so that you don’t have dependencies to the Silverlight runtime and just run the tests on the desktop framework. I’ve done all the techniques out there but never been happy with the flow. This is an ongoing things.

Are we there yet?
Phew.. So, were are we at?  Balder has a default branch which is still on the SL4 level where I left off over a year ago and there is a parallel branch for the SL5 parts and all the refactorings and changes that had to be done to bring Balder to SL5. There are some bugs and quirks in it and development is not going as fast as I would have hoped. There are a few reasons for that, one is the lack of tests and not a good story for retro fitting them. I’ve started doing it with MSpec and writing in a specification way instead, made it a lot easier but there is still a lot of work to be done there. The second reason things are going slow is that Microsoft has yet to come up with a good cross platform story for the 3D bits, in fact, thus far there is none – it only works on Windows for now. I’ve been probing them to get an answer, but haven’t gotten one yet. To be honest, it has for a while halted my motivation for moving forward at the same pace, until last week when I had a breakthrough in rendering that increases performance quite a bit and also the quality for software rendering, which will then prove as the fallback solution for Mac.

Deferred software rendering

In addition the latest versions of the most used browsers on Mac supports WebGL, which is something that can be used directly from Silverlight as well. After getting the software rendering fallback done, I’ll start looking at the WebGL approach as a second fallback scenario for those browsers that supports it.

Another aspect of the SL5 codebase is that Microsoft changed security from the beta released at Mix to the version released at Build which lead to in-browser shaders not being allowed to do loops. Balder supported 5 light sources with the pixel shaders I wrote for the Beta version, but can only do one with the latest version of SL5. In order to fully support an arbitrary number of lights I’ll have to move over to deferred rendering and that has quite a few implications on how Balder works as well. But a job I’ve started and will make it the default rendering method across the board for now.

But all that being said, there are some critical issues that needs to be solved – they are issues that really makes it hard for me as a developer to get the velocity I want, so I will be going back and forth researching and bringing back the code quality I want to feel comfortable.

 

So, what about the tag-line of Balder and devices?
A couple of years ago I saw the opportunity to bring Balder onto more devices and started optimizing the code-base and extension points to be able to bring to things like the Windows Phone 7, iOS, Android and others. This is something I’d still love to do, but will not focus on it for quite a while. There is still too much work on the Silverlight side to justify focusing on devices just yet. There is a version of Balder for WP 7, but not for the latest Mango and to be honest, WP7 is in fact the hardest of these devices to get any proper rendering on since one is not allowed to write shaders for that device.

 

Conclusion
As you might understand, Balder is still active – not just at the same pace as before, hoping to pick this up a little bit moving forward. There are some code-rot that needs fixing, increase of code quality and things like that holding back development a bit, but also technical challenges with the platform. Since I’m relentless with the cross-platform part and am not willing to budge on it, I will focus my energy on getting that working and hopefully working good. If this was a commercial product, I would probably not go to the lengths I am to get the cross-platform parts working, but one has to remember that my original motivation for going down the road of creating Balder in the first place was based upon cross-platform – take that out and personally I will lose the biggest motivation I’ve had with the project.

I’ve established a Trello board were people can see what I’m focusing on these days for Balder.

 


Standard
.net, C#

MVVM in Windows Forms

Not everyone has the luxury of jumping on new technologies, it can be historical reasons, don’t have time to learn, deployment reasons – or flat out you simply don’t like anything new 🙂 .

Anyways, I was doing a codereview on a project last week, which was written in Windows Forms. The developers had some pain, Windows Forms being one of them – and a constant feeling that they were barking up the wrong tree when using Windows Forms. Its been a couple of years since my last Windows Forms project, and I must admit I remember the feeling of constantly banging my head against the wall without getting the code quality I wanted when doing UI.

One of the things I saw that the project could benefit from, was unit testing – to help them fight problems with regression, and get a constant quality indicator on the project. Having done a lot of WPF and Silverlight over the years and leaving Windows Forms behind, it just felt bad not having a proper UI pattern and I’m loving MVVM and the way it works – the simplicity of it. So I decided to do a spike, how could one implement MVVM in Windows Forms and get all the niceness of testability and full separation.

Keep in mind, I haven’t done a full implementation of a framework or anything, just the basics to get started. The one thing I wanted was to be able for the view (Form or UserControl) to be able to observe changes from a ViewModel. Windows Forms does in fact recognize the interfaces we are so familiar with from WPF and Silverlight (INotifyPropertyChanged and INotifyCollectionChanged), so it was just a matter of figuring out how to get the ViewModel easily accessible in the designer in Windows Forms. I came up with something called ViewModelBindingSource. A very simple component that can be dragged onto the designer surface:

 public class ViewModelBindingSource : BindingSource
 {
 public ViewModelBindingSource(IContainer container)
 : base(container)
 {
 }

private object _viewModel;
private Type _viewModelType;

[Category("MVVM"), DefaultValue((string)null), AttributeProvider(typeof(IListSource))]
public Type ViewModel
{
 get { return _viewModelType; }
 set
 {
 SuspendBinding();
 _viewModelType = value;
 _viewModel = Activator.CreateInstance(_viewModelType);
 Add(_viewModel);
 MoveFirst();
 ResumeBinding();
 }
}

public override object this[int index]
{
 get
 {
 return _viewModel;
 }
 set
 {
 base[index] = value;
 }
}
}

The next thing I wanted to accomplish, was the ability to hook up Commands for Buttons and such, supporting the ICommand interface found in WPF. I came up with a CommandExtenderProvider:

[ProvideProperty("Command", typeof(Button))]
public class CommandExtenderProvider : Component, IExtenderProvider
{
private readonly Dictionary _buttonsWithCommands;
private readonly List _uninitializedButtons;
public CommandExtenderProvider()
{
_buttonsWithCommands = new Dictionary();
_uninitializedButtons = new List();
}
public bool CanExtend(object extendee)
{
return extendee is Button;
}
private BindingSource _viewModelSource;
[Category("MVVM")]
public BindingSource ViewModelSource
{
get { return _viewModelSource; }
set
{
_viewModelSource = value;
InitializeUninitializedButtons();
}
}
private void InitializeUninitializedButtons()
{
foreach( var button in _uninitializedButtons )
{
var commandName = _buttonsWithCommands[button];
SetCommand(button, commandName);
}
_uninitializedButtons.Clear();
}
[Editor(typeof(CommandEditor), typeof(UITypeEditor))]
public string GetCommand(Button button)
{
if (!_buttonsWithCommands.ContainsKey(button))
{
return null;
}
var command = _buttonsWithCommands[button];
return command;
}
public void SetCommand(Button button, string commandName)
{
_buttonsWithCommands[button] = commandName;
if (null == ViewModelSource ||
null == ViewModelSource.Current)
{
_uninitializedButtons.Add(button);
return;
}
var property = ViewModelSource.Current.GetType().GetProperty(commandName);
if (null != property)
{
var command = property.GetValue(ViewModelSource.Current, null) as ICommand;
if (null != command)
{
button.Enabled = command.CanExecute(null);
command.CanExecuteChanged += (s, e) => button.Enabled = command.CanExecute(null);
button.Click += (s, e) =>
{
if (command.CanExecute(null))
{
command.Execute(null);
}
};
}
}
}
}

In the designer, you’ll get two new components you can then drag onto your Windows Forms design surface:

Simply start by dragging in the ViewModelBindingSource and look in the Properties of it. Under the MVVM category, you’ll find the property ViewModel – a dropdown were you can select the ViewModel.

If you then drag onto the design surface a TextBox that you want to have databound to a property in the ViewModel and look in the Properties window for the TextBox. There you’ll find your ViewModelBindingSource, expanding it will show all the properties available in the ViewModel:

For commands, we need the CommandExtenderProvider. That too can be dragged onto the surface. It has a property for selecting the ViewModelBindingSource:

Now you can add a button to the surface and go to properties, you’ll find a property called Command. There you can select the command you want to be executed during Click.

There is still a bunch of things to be desired in order for this to fully support all aspects of MVVM. But it proves its possible to think in this way, even though your technology is not necessarily state of the art.

Hope anyone finds this interesting.

The source code can be found here.

 

Standard
.net, 3D, Balder, C#

Balder – 0.8.8.9 very close

Its been a hectic week – but finally most of the pieces are falling into place for the next release. There is only a couple of minor features I want to add before calling it a release. Meanwhile, I’ve updated the samplebrowser and released it as a sneak peak. I’ve replaced the Material Picker sample with a Material Editor were you can actually edit all the properties of the materials and also the lights added to the scene.

Here’s a screenshot of how it can look like when configured with all features enabled:

Balder_0_8_8_9_Preview
If you’re having trouble with the SampleBrowser on Safari or Chrome on the Mac, this is something I’m investigating. I’ve tested it with all browsers on Windows and Mac, but these two had some issues when textures were involved on my machine. Will look into it more carefully before releasing the next version. The odd thing though, it worked with the samplebrowser compiled as debug.

 

Standard
.net, 3D, Balder, C#

Clarifying Balders feature set

Hopefully I’m not forgetting anything (probably am) – but below is a clarification of what features Balder has.

Coordinate system

Balder uses a left-handed coordinate system – currently there is no way to change this, but there are plans for opening up for any coordinate system.

Nodes

  • Interaction – one can enable interaction on any nodes and they can be interactively manipulated during runtime
  • Position coordinates
  • Rotation coordinates, in angles for each axis
  • Scale coordinates
  • Hierarchical rendering of nodes

Scene

  • A Scene contains objects, any Balder object implementing the interface INode; Lights, geometries, sprites

Viewport

  • Defines a clipping area on the screen, coordinate relative to its container

View

  • Camera
    • Position
    • Target
    • Field Of View

Sprites

  • Flat image based objects that exist in 3D space – they are rendered along with other 3D content and positioned and scaled correct according to their 3D space position.

Geometries

  • Box – simple box with dimensions
  • Cylinder – top and bottom dimensions can be specified independently
  • Ring – inner and outer circle dimensions can be specified independently
  • ChamferBox – simple box with a chamfer segment
  • HeightMap – a plane that consist of a set of vertices (points) that can be manipulated by its height
  • ArbitraryHeightMap – a derivative of HeightMap, but its plane is arbitrary
  • Mesh – a complex mesh which can be loaded from a file

Other objects

  • Container – not renderable itself, but can contain any Node in it – hierarchically

Assets

All data loaded from disk or elsewhere is known as Assets. There are Asset loaders for file types, you can even create your own Asset loaders quite easily. For Silverlight, there exist today a limitation which only allows loading of assets found in the XAP file – meaning that any asset added to the project must be a Resource in the XAP file. This is being worked on and will in a future release be more flexible.

  • ASE file – supports 90% of the Autodesk Ascii Scene Export format for 3D objects
  • Experimental support for Demoniak3D format
  • JPEG, PNG for Images

Assets are cached in a content manager, which means that if you load the same asset twice, it will clone the first one.

Lighting

  • OmniLight – non directional light, emits light in all directions
  • DirectionalLight – emits light in a specific direction, without any starting point or ending point
  • ViewLight – view dependent light that will always emit from the view and into the Scene

Rendering

  • Z buffered rendering
  • Flat shaded – single color faces
  • Gouraud shaded – color can be specific on each corner of a triangle
  • TextureMapping – perspective corrected, gouraud shaded.
  • Lines
  • Passive rendering mode – renders only when there are changes
  • Bilinear filtering
  • Face-culling – do not render faces/triangles facing away, can be controlled via Materials
  • Frustum-culling – objects not inside view will not be rendered – increases performance a lot

Materials

  • Diffuse color
  • Diffuse map
  • Ambient color
  • Specular color
  • Reflection map
  • Opacity for the different maps can be specified

Imaging

  • Supports PNG and JPEG
  • For textures, you must use images with dimensions being power of 2 (2,4,8,16,32,64,128,256,512,1024 and so on)

Input

  • For Silverlight; mouse events are supported (MouseEnter, MouseLeave, MouseMove, MouseLeftButtonDown, MouseLeftButtonUp)
  • Manipulation events for all Nodes to make it easier to interact with objects

Debug visualization

  • Bounding information
  • Show vertices

Statistics

  • Rendering timing
  • Amount of faces being rendered
  • Amount of objects being rendered

Execution

  • Actor system with statemachine for actors in the scene
  • Game – base class for any game

Silverlight / Windows Phone 7 specifics

  • Full XAML support – you can declaratively do everything that Balder can do in XAML
  • Specific CoordinateAnimation that can be used in storyboards for animating properties on Nodes
  • NodesControl / NodesStack – databindable controls that be bound to any source with NodeTemplate to specify its representation on screen. Similar to ItemsControl found in Silverlight.


Standard
.net, 3D, Balder, C#

Balder – vertex colors

I’ve been working lately on a demo that is for gaming a lot more realistic than the spinning teapot or box that one sees in the sample browser for Balder. A friend of mine Peter Rosenlund, an excellent graphics artist, gave me a 3D model of a city that I can use for that (thanks a lot!!).

In the 3D model, he had applied static lighting manually in 3DSMAX by painting the Vertex colors – a feature I had not implemented in Balder. After a few hours yesterday and this morning, I got it all up and running and I must say it looks kinda nice.

Balder, rendering city without vertex colors applied:

Balder_Without_VertexColors

Balder, rendering same city with the vertex colors applied:

Balder_With_VertexColors

 

Standard
3D, Balder, C#

Balder – Upcoming release

Its been some 4 months since the last official binary drop of Balder and its just about time to get a new version out. The reason for the "hold up" is that I've been quite busy with working 2 jobs; my daytime job and Balder related freelance work at night. Combining that with having a family of 2 kids and a wife, there simply hasn't been any time left get binaries out there. 

But, as part of the work that I've been doing freelance, Balder has gotten a lot of improvements. Among these are the following : 

– Further optimizations in the rendering pipeline

– Rewritten NodesControl, speed up and more capable

– General cleanups

– More Xml comments for documentation purposes

– Retrofitted some unittests

– Mouse events working properly

– Tooltip for Nodes

– Arbitrary Heightmap – corners of heightmap can be placed anywhere

– New AseLoader with more support than before (Smoothings groups, more objects, more material details, colors++)

– Rewritten AssetLoader system

– Fixed bugs with primitives

– More samples in SampleBrowser

– Visual Studio 2010 solution + project files

– Optimized lighting

– Added ViewLight – lighting relative to view, basically directional lighting

– Passive Rendering, making the rendering halt unless properties are changed on any object in the scene

– Content caching for faster startups

– A lot of code cleanups for decoupling the platform even more

– Material detection for mouse events 

 

And a whole bunch of other improvements.

The only thing left before a release can be done is to tie together some lose ends and fix a couple of bugs – then its ready for deployment. I'll be sure to post about all the new features and how they can be used in a post when the release is ready.

The next iteration will focus more on increasing code quality, more cleanups, get more documentation up and running, continuous integration server up and running and things that will improve further development on the project. 

Standard
.net, C#

First go with the EQATEC Silverlight Profiler

Its been a little more than 24 hours since I started playing with the EQATEC profiler and have identified bottlenecks in Balder that is close to impossible to discover without a profiler. One of things I really liked about the EQATEC profiler was its really easy to use user interface, its super-intuitive and I got up and running in seconds and could drill down straight to the bottlenecks just as fast. What impresses me with the profiler is the speed of it, I've worked with quite a few profilers in the past for the desktop – and they have always surprised me in a negative way with the amount of memory they use and not to mention the enourmous datafiles they generate. EQATECs just feels right, kudos to Richard Flamsholt and his team in Denmark for this product. You can download a free/personal license from here.

I thought I just give a quick guide into how its used.

The profiler is not integrated in Visual Studio and does not need to instrument your assemblies during compiletime, it works on the binary output of your compiled output. After starting the profiler, you need to point the profiler to your output directory in which the binaries for your application resides, typically the bindebug directory in your Visual Studio project folder. Click the browse button as shown below:

The first time you run it and if you have 3rd party assemblies that are signed you'll be asked to include or exclude these – the default recommendation is to exclude these. There is a resigning option included as well, but I didn't need this so I just skipped them. After it completes gathering your assemblies and recognizes the Silverlight app by finding the testpage and everything, you can go ahead and click the Build button in the lower right corner. It will instrument your binaries and add hooks for all your methods.

Then you just simply click the "Run App" button and your application will start and performance samples will be collected. You now need to play around in your application for the profiler to get enough data to play with.

After stopping your application, you'll be presented with the sample output with details of when it was profiled, its size and total time it ran.

Double click the session you want to view (if you have more than one) and you can start to drill into method calls with the summary sitting on top and a more visualized version of the method with drilldown capabilities at the bottom.

 

 Simple drill down and you'll see the amount of time spent in every method you drill down into:

 

And further: 

 

 

This is by far, in my oppinion, the best tool that has been released since Silverlight was released. It completes the developer experience and finally we can really show the full potential of Silverlight and the power the CLR actually gives us.

Thanks again to EQATEC for the donation to Balder – we will certainly make use of the license and optimize as close as we can to clock-cycles. 🙂 

 

 

Standard
.net, 3D, C#

Balder 0.8.8.6 is out

UPDATE 8th of July 2010 : 0.8.8.7 is out – read more here.

Finally after a couple of months of hard work and polishing the code, API and performance, version 0.8.8.6 ofBalderis out. A SampleBrowser can be found here for viewing most of the features ofBalder.
The features that has changed or is new are as follows:

* Introduced Silverlight in Core, but still maintaining platform independence
– Using core objects directly in Xaml can now be done

* Removed all controls in Balder.Core.Silverlight.Controls – not needed anymore

* Introduced View namespace with IView interface and Camera implementing it

* Viewport has View property insted of Camera

* Moved rendering from a multithread environment to run synchronously on the CompositionTarget. It gives better performance, due to synchronization issues between all threads. Will be revisited in the future.

* New drawing routines, optimized

* Heightmap primitive

* Box primitive

* Rotation, Scale on nodes

* Cylinder primitive

* DebugLevel is known as DebugInfo

* Material system in place

* Support for ReflectionMapping on materials

* Double sided materials

* Sprite rendering with alpha channel

* NodesControl – datadriven nodes control with templating – In Balder.Silverlight.Controls

* NodesStack – datadriven stacking of nodes with templating – in Balder.Silverlight.Controls


Standard
.net, 3D, C#, Game Development, Optimizing

Upcoming Balder release – 0.8.8.6

Its been crazy weeks since I decided to pull 0.8.8.5, but it was for the better. The result is that the rendering speed and quality has gone up quite dramatically. The next version of Balder will be 0.8.8.6 and will contain at least the following: 

– Optimized framebuffer management

– Optimized drawing/rendering

– Optimized lighting

– Proper polygon clipping against the viewport 

– Completely refactored way of handling objects, no duplication in the type hierarchy for Balder, like in 0.8.8.0.

– New controls : NodesControl, NodesStack – similar as Canvas and StackPanel works with 2D elements in Silverlight

– New geometry types; Box, Cylinder, Plane

– Transparency for objects / materials

– Introducing the concept of View, you can now create custom cameras

– DebugLevel is no longer flag-based, but a self contained object with properties for all Debug options

– Rendering is now synchronously – gives better framerate in most scenarios, but hogs up rendering event. Ongoing process.

 

Its been crazy since december with a lot of work being put into Balder and more to come. I don't have a date yet for when I'll have the release, but I'll try to push it as soon as I'm content with the result. 

 

Standard
.net, C#

Dispatcher Safe INotifyPropertyChanged

Update, 19th of November 2011:

Eduardo Elias Mardini Bitar did an article for the CodeProject with some updates and improvements.

 

One of the things I really love in Silverlight is the promotion of non-locking UIs through heavy use of asynchronous operations for things like webservice calls. The main problem though with this is that it is running on a different thread than the UI thread and you can't modify anything on the UI without running on the same thread. This even goes for databinding, so if you have properties on an object databound in the UI and you set the value on any of these properties, you still need to be on the UI thread in order for this to work. This is also true for WPF applications.

The way you could do this is to get an instance of the Dispatcher and use the BeginInvoke() method on it. In Silverlight there is only one Dispatcher and it can be retrieved from the Deployment object in System.Windows; Deployment.Current.Dispatcher. In WPF there can be several Dispatchers, so it gets a bit more complicated, you'd have to do Dispatcher.FromThread() and use the current thread during the add method of your PropertyChanged and store it alongside with the instance of the delegate to know which Dispatcher to invoke a change on.

 When I first wrote my automagically implemented INotifyPropertyChanged post, it didn't have this support. I knew I needed it to support it, but I didn't want to have a dependency directly to the Dispatcher found in the Deployment object, as my unit tests would have a hard time coping with that dependency. I needed to abstract it away so I could have a cleaner way of doing this and be able to test it without too much hassle. By introducing an interface representing the Dispatcher, I was halfway there, but had no way of injecting this into the proxy types being created. The problem is that you can't define a constant on the type that holds a reference to a ref object, it only supports value types. I really struggled a full day with this, I was trying to not have any dependencies from the proxies in order to get the Dispatcher, and I didn't want to tie it up to just be compatible with IoC containers and specifically NInject that I'm using for the most part. The result is that I had to implement a DispatcherManager and have a private field on the proxy type holding a reference to an IDispatcher and let the manager control which implementation it got. This worked out nicely, even though it now have a dependency to the DispatcherManager directly. 

This has all been implemented into the Balder project, as I need it for my SampleBrowser I'm working on, the code is located inside the Notification namespace and can be found here

What does it do?
Lets say you have your object like below, the virtuals are in there for the weaver to be able to implement these properties in its proxy (as eplained in my previous post). 

[code:c#]
public class Employee
{
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; } 
}
[/code]

The weaver will then go and inject its magic, the end result is pretty much like this:
[code:c#]
public class EmployeeProxy : Employee, INotifyPropertyChanged
{
    private IDispatcher _dispatcher = DispatcherManager.Current;

    public event PropertyChangedEventHandler PropertyChanged;

    public override string FirstName
    {
        get { return base.FirstName; }
        set
        {
            base.FirstName = value;
            OnPropertyChanged("FirstName");
        }
    }

    public override string LastName
    {
        get { return base.LastName; }
        set
        {
            base.LastName = value;
            OnPropertyChanged("LastName");
        }
    }

    private void OnPropertyChanged(string propertyName)
    {
        if( null != PropertyChanged )
        {
            if( _dispatcher.CheckAccess() )
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            else
            {
                _dispatcher.BeginInvoke(PropertyChanged,this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

}
[/code] 

Standard