Easier PropertyChanged notification with PostSharp

As I described in this previous article raising the PropertyChanged event for classes that implement INotifyPropertyChanged can be a real pain. The biggest problem is that PropertyChangedEventArgs takes the name of the property that changed as a string and as we all know, strings are the root of all evil. Here I will show how to use a simple PostSharp attribute on your properties that need to raise the PropertyChanged event when they are changed so that you don’t manually need to do it and hard code the name of the property as a string. PostSharp is a framework for .NET that allows for aspect oriented programming. You can read all about it at the PostSharp website.

First of all, let’s assume that the classes implementing INotifyPropertyChanged are model view classes in the MVVM pattern. We will use a base class for all model views called BaseModelView that looks like this:

Imports System.ComponentModel
 
''' <summary>
''' Parent class for all model views
''' </summary>
Public Class BaseModelView
    Implements INotifyPropertyChanged
 
    Public Event PropertyChanged( _
        ByVal sender As Object, _
        ByVal e As System.ComponentModel.PropertyChangedEventArgs) _
        Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
 
    ''' <summary>
    ''' Raises the <c>PropertyChanged</c> event for the property with the given name.
    ''' </summary>
    ''' <param name="propertyName">The name of the property that has changed.</param>
    ''' <remarks>If there is no property on this class with the given name, then an
    ''' exception will be thrown.</remarks>
    Public Sub OnPropertyChanged(ByVal propertyName As String)
 
        ' Throw an exception if the property doesn't exist
        If Me.GetType().GetProperty(propertyName) Is Nothing Then
            Throw New ArgumentException( _
                String.Format("The property {0} doesn't exist on type {1}.", _
                              propertyName, _
                              Me.GetType().Name))
        End If
 
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
 
    End Sub
 
End Class

This class is very important. There needs to be a method for property change notification (ie: OnPropertyChanged on BaseModelView) instead of just an event (ie: PropertyChanged on INotifyPropertyChanged) because the attribute cannot directly raise an event, but it can call a public method that raises the event. The PostSharp attribute looks like this:

Imports PostSharp.Laos
Imports System.ComponentModel
 
<Serializable()> _
Public Class NotifyAttribute
    Inherits OnMethodBoundaryAspect
 
    Public Overrides Sub OnExit(ByVal eventArgs As PostSharp.Laos.MethodExecutionEventArgs)
        ' Convert to BaseModelView
        Dim notifier = TryCast(eventArgs.Instance, BaseModelView)
 
        ' If the instance is the wrong type then throw an exception
        If notifier Is Nothing Then
            Throw New InvalidOperationException("Cannot raise PropertyChanged event unless instance implements INotifyPropertyChanged.")
        End If
 
        ' Ignore everything that's not a setter
        If eventArgs.Method.Name.StartsWith("set_") Then
            notifier.OnPropertyChanged(eventArgs.Method.Name.Substring(4))
        End If
    End Sub
 
End Class

Note that when you apply PostSharp attribute to a property, you are actually applying the attribute to the two methods that are generated for that property. For example, if you have a property called MyProperty then the compiler will actually generate two methods: get_MyProperty and set_MyProperty. Since OnExit() will actually get called for both of these methods when we apply the attribute to a property, the code has to check whether the getter or the setter was called. Using the attribute is very simple:

<Notify()> _
Public Property Text() As String
    Get
        Return _text
    End Get
    Set(ByVal value As String)
        _text = value
    End Set
End Property

The result is that the PropertyChanged event will automatically be raised after the setter finishes executing and there is no need to hard code any strings! Now you are free to change the name of your property and it won’t break any code.

WPF rendering thread synchronization

Download the sample project here: WpfRenderingThreadSynchronization.zip

In most applications it is necessary to offload long running processes to an alternate thread so that the rest of the program does not lock up during that time. However, it’s not so simple when the long running process is the actual rendering. Separate windows can have their own UI threads (as explained here) but to my knowledge there is no way to use multiple rendering threads on a single window.

The second problem is that rendering is done in big chunks. For example, if you have an ItemsControl that is bound to an ObservableCollection and a loop that adds 1000 items to that collection, you will notice that the elements are not drawn one at a time. Instead the UI will stall for a moment and then every element will suddenly appear on screen. During the time that it is loading, the entire window will be completely unusable. Basically, what happens is that UI changes (like adding an element to an ItemsControl’s ObservableCollection) all get put into a queue and then the rendering thread deals with a whole bunch of them all at once.

There are two problems with this behaviour:

  • The rest of the UI is unusable while this loading takes place
  • It’s not obvious what is happening during the loading period. Since absolutely nothing is happening on screen, the user might think the app is broken.

It turns out that in cases like this where we have many small rendering operations that add up to a large amount of time, we can force the rendering thread to flush out the Windows message queue after each element is added to the collection. This will not only allow the user to see progress (ie: items appearing in the ItemsControl one at a time) but between each item being added other UI updates can take place giving the illusion that there are separate UI threads.

The included sample draws 1000 TextBoxes inside an ItemsControl, but after each element is added the Windows message queue is flushed out using the FlushWindowsMessageQueue function. All the functions does is tell the dispatcher to invoke a delegate that does nothing. The result is that the code blocks at that line until the specified delegate has been run. But since it is at the end of the queue, everything else has to be dealt with first. The function looks like this:

Private Sub FlushWindowsMessageQueue()
    Application.Current.Dispatcher.Invoke( _
        New Action(AddressOf DummySub), _
        DispatcherPriority.Background, _
        New Object() {})
End Sub
 
Private Sub DummySub()
End Sub

When the sample is run with the FlushWindowsMessageQueue() line commented out the whole UI will lock up for a couple of seconds after you click “Refresh data”. However, when the message queue is emptied after each element is added the UI never locks up, even when it is still drawing TextBoxes.

Unfortunately, there are some drawbacks to this method. The most obvious is that it makes the entire rendering operation actually take longer. The trade off is that the first items appear much earlier, but the last items appear later. The technique also cannot be used when the rendering cannot easily be split into many small chunks.

SVN with Visual Studio

Here are some tips for using SVN with a Visual Studio project:

Choosing a client

There are quite a few SVN clients out there. If you like to have one built in to the IDE, then there’s Ankh SVN and Visual SVN. I have used Ankh but found it to be a little buggy (those issues may have been resolved by now) and I have never used Visual SVN because it costs money. I prefer not to have my SVN client built into the IDE though because I often need to do SVN operations outside of Visual Studio anyways. It can also complicate the process a little bit. For example, if you just want to commit your solution file with Ankh, you would probably right click on the solution and choose commit, but this actually commits everything in the solution, not just the solution file. If you use an external client like Tortoise SVN or Rapid SVN then you will get full control over your SVN activity. Both clients are good. Tortoise is a windows explorer extension, while Rapid is a standalone app. Personally, I use Tortoise, but some people don’t like anything that messes with the explorer.

What not to commit

Most of the time you do not want to commit your binary files, just the source, so you should tell SVN to ignore the bin and obj folders in each project. Every solution also has a .suo file that stores the state of the IDE (eg: the files you have open). So for example, if user X commits his .suo file and user Y does an update, then when user Y reloads the project it will open the windows user X was viewing, not the ones user Y was viewing. This isn’t normally the desired behaviour, so you should also ignore the .suo file (it’s in the same directory as the .sln file).

External libraries

When your solution and project files are being versioned, you don’t want to have references to DLLs on your hard drive with absolute paths. Instead, it is ideal to include a folder called lib in your project and put all your DLLs in there so that the entire folder can be included in SVN, ensuring that the references will work for everyone.

Updating from an external client

If you use an external SVN client like Tortoise or Rapid then you do not need to close Visual Studio to do an update, but for the love of god, make sure to save your files before you update. If any of the files or projects you have opened are changed by the update you will be asked whether to reload them. Say yes (if you have files with unsaved changes those changes will get overwritten, that’s why you need to save before updating). This can take a few seconds if any large projects need to be reloaded. After it’s done you might see a bunch of compile errors. Usually they will disappear with a simple compile, but sometimes false errors will still be displayed until you do a full rebuild of the solution. If the compile errors persist then it is likely a legitimate error and you need to take to whoever committed last.

Omitting certain projects in a solution

If you have a project in your solution that you do not want to commit (eg: a test project) then it is not enough to simply ignore the files for that project. If you just ignore the files and commit, then when another user gets your update they will receive an error saying that the project you omitted cannot be found. This is because the .sln xml file keeps track of the projects in your solution, so now it contains a reference to a project with no files. To prevent this you need to right click on the project in Visual Studio and choose “Remove” before committing. This will just remove the project from the solution, it won’t actually delete any files. Note: removing the project changes the .sln file, but it does not automatically save those changes. In order to save the .sln file you need to recompile the solution or do a “save all” (ctrl+shift+S).

Don’t let “Option Strict Off” make you lazy

VB.NET has the sometimes useful feature of late binding, but this seems to lead to poor code. By default, late binding is enabled (ie: Option Strict is set to Off) allowing for implicit narrowing conversions (no cast). Although there are certainly cases where this is a useful feature that can cut down on the amount of reflection code left up to the programmer, I have found that it is more often a cause of less robust code and needless performance degradation.

With Option Strict Off we can write code like this:

Dim obj As Object = "Hello, World!"
Dim str As String = obj

In this case the code will run just fine, and it saved us the hassle of casting obj to String. However, we will obviously run into problems in a situation like this:

Dim obj As Object = "Hello, World!"
Dim int As Integer = obj

Even though int is an Integer this code will compile, but at runtime there will be an InvalidCastException. This is all pretty simple stuff, but the bottom line is that in this case, Option Strict Off gives a runtime error, while Option Strict On gives a compile error. The value of compile-time errors should not be taken lightly, and in my humble opinion they are a programmer’s best friend. With Option Strict On our first sample only needs a minor change:

Dim obj As Object = "Hello, World!"
Dim str As String = DirectCast(obj, String)

Was it really that difficult just to cast it? Type casting is not an inconvenience, but a necessary precaution requiring the programmer to say to the compiler: “Yes, I did intend to perform a narrowing conversion. It was not an accident”.

As a general rule of thumb, I like to set Option Strict On as the project default (go to Project -> Properties -> Compile) and then add Option Strict Off to code files that require it rather than the other way around.

Verify your property names in INotifyPropertyChanged implementation

Update: I have posted another article here that explains what I think is a better solution to this problem using a simple PostSharp attribute.

When you raise the PropertyChanged event you have to pass it a property name as a string. If there is no property with that name then nothing will happen. The listener will not be notified and no exception will be thrown making the problem very difficult to debug. You can change this behaviour and make the application fail at runtime by adding a simple check to your helper function for the event:

Public Sub NotifyPropertyChanged(ByVal propertyName As String)
    ' Throw an exception if the property doesn't exist
    If Me.GetType().GetProperty(propertyName) Is Nothing Then
        Throw New InvalidPropertyNameException()
    End If
 
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub

If you put this in a base class for all of your model views (or controllers, or presenters) then you will automatically get this functionality every time, preventing some potentially very annoying bugs.

This still isn’t the ultimate solution because you don’t find out that the property name doesn’t exist until runtime. Ideally, we would get a compile error when the property does not exist. What I would like to do is call the function like this:

NotifyPropertyChanged(AddressOf MyProperty)

This way you wouldn’t have to use a string at all and the compiler would tell you if MyProperty doesn’t exist. Unfortunately, .NET languages only have delegates for functions/subroutines so there is no way to make a strongly typed pointer to a property. Let’s hope they add that in one day, but until then, we’ll have to use strings.

Nullable combo boxes in WPF

Update: Sample source code demonstrating this technique can be downloaded here: WpfNullableComboBox.zip

By default, combo boxes in WPF have some really annoying behaviour. When the control is initialized, if the SelectedItem is Nothing then the default selection will be blank, but as soon as you choose an item in the combo box, you can not reselect the blank/null option. One quick way around this is to add a null placeholder object to your ItemsSource. There are a few problems with this approach though:

  1. The null placeholder cannot actually be Nothing/null or else selecting the value will have no affect. Instead, it needs to be some object that represents “null”. This means that if you want your setter on the property bound to the SelectedItem to be set to null, you need to convert the object representing null to actually be Nothing/null.
  2. Ideally, you should not have to alter the collection in your model view/controller/presenter that is bound to the ItemsSource just to add a null option. It would be better if we could just specify in XAML that this combo box should have a null option that actually sets the SelectedItem to Nothing.

Since we don’t want to alter the collection in the controller and we cannot have a combo box item of Nothing (we need a null place holder object instead) but we don’t want the SelectedItem property to ever have the null place holder object as its value (we want it to just be Nothing when that is chosen) we can do one of two things:

  1. Use two converters: one on the ItemsSource to add in the null place holder object and one on SelectedItem to convert the place holder to Nothing.
  2. Create a user control that acts as a wrapper around the combo box control. All the necessary logic could be handled within the user control.

Option one would look like this:

<ComboBox
    ItemsSource="{Binding MyItems, Converter={StaticResource addNullPlaceHolderConverter}}"
    SelectedItem="{Binding MySelectedItem, Converter={StaticResource placeHolderToNullConverter}}" />

In my opinion, that method really sucks. You have to add the converters in you resources section and then specify them in two places. Another issue is that we could run into some major converter explosion if it turns out that you already need some other converter on one of the properties. Then you have to make a new converter that combines the two. I don’t like it.

Option two looks like this:

<local:NullableComboBox
    ItemsSource="{Binding MyItems}"
    SelectedItem="{Binding MySelectedItem}" />

Much better!

The XAML for the user control is extremely simple. You just need to create a combo box with a name:

<UserControl x:Class="NullableComboBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ComboBox x:Name="combo" />
</UserControl>

In the code-behind you need to expose two dependency properties: SelectedItem and ItemsSource so that the control has the same interface as a regular combo box.

By listening to the combo box’s SelectionChanged event you can update the SelectedItem property on the NullableComboBox except with the place holder converted to Nothing.

Brutal loading times deleting files in Visual Studio

I have long had an issue with Visual Studio where it takes a ridiculous amount of time to delete a file. Sometimes it takes over a minute and the IDE is completely unusable while it is loading. I finally came across a this post by Matt Hinze that gives a solution. Apparently when you delete a file it scans your recycle bin which can take a long time if there are lot of files in there. All you have to do is empty your recycle bin and you should be able to delete files with no noticeable delay.

Forcing form validation in WPF before user input

By default, validation is not enforced on a binding until after the value has been changed once. Consider this situation: A form has a text box whose contents should not be empty, but its starting value is the empty string. The text box will not show an error when the form is loaded. Instead, it will only show its error style after the user types in some text and then deletes it. Some people would call this a feature, but I prefer to have the validation checked right away so that I immediately know what the required fields are, and which starting values are invalid.

A quick hack

One way to tackle this is to hook a loaded event to the control and then call UpdateSource() from code:

Private Sub myTextBox_Loaded(ByVal sender As System.Object, _
        ByVal e As System.Windows.RoutedEventArgs) Handles myTextBox.Loaded
 
    BindingOperations.GetBindingExpression(myTextBox, _
        TextBox.TextProperty).UpdateSource()
 
End Sub

Unfortunately, this really isn’t a desirable solution because it requires some pretty ugly code-behind (not that there’s any other kind) and needs to be done over again for every binding. What we really want is for this functionality to be a part of the binding markup extension.

Creating a wrapper around the binding markup extension

At first I thought it would be easy to just inherit from the Binding class and override ProvideValue, but of course, it is marked as NotOverridable (sealed in C#). Instead, I create a class called ValidationBinding that inherits directly from MarkupExtension and has the new class manage an instance of Binding. The code looks like this:

Imports System.Windows.Markup
 
Public Class ValidationBinding
    Inherits MarkupExtension
 
    Private _binding As New Binding
    Private _dependencyObject As DependencyObject
    Private _dependencyProperty As DependencyProperty
 
    Public Sub New()
        _binding.ValidatesOnDataErrors = True
        _binding.ValidatesOnExceptions = True
    End Sub
 
    Public Sub New(ByVal path As String)
        Me.New()
        _binding.Path = New PropertyPath(path)
    End Sub
 
    Public Overrides Function ProvideValue _
        (ByVal serviceProvider As System.IServiceProvider) As Object
 
        Dim valueTarget = _
            DirectCast(serviceProvider.GetService(GetType(IProvideValueTarget)),  _
            IProvideValueTarget)
 
        _dependencyObject = valueTarget.TargetObject
        _dependencyProperty = valueTarget.TargetProperty
 
        If TypeOf _dependencyObject Is FrameworkElement Then
            Dim element = DirectCast(_dependencyObject, FrameworkElement)
            If element.IsLoaded Then
                ForceValidation()
            Else
                AddHandler element.Loaded, AddressOf ElementLoaded
            End If
        Else
            ForceValidation()
        End If
 
        Return _binding.ProvideValue(serviceProvider)
 
    End Function
 
    Private Sub ForceValidation()
        BindingOperations.GetBindingExpression(_dependencyObject, _
                                               _dependencyProperty).UpdateSource()
    End Sub
 
    Private Sub ElementLoaded(ByVal sender As System.Object, _
                              ByVal e As System.Windows.RoutedEventArgs)
        ForceValidation()
    End Sub
 
    Public Property Path() As PropertyPath
        Get
            Return _binding.Path
        End Get
        Set(ByVal value As PropertyPath)
            _binding.Path = value
        End Set
    End Property
 
    ... the rest of the binding properties go here
 
End Class

The binding can then be used like this (where my is an imported namespace containing ValidationBinding):

<TextBox Margin="5" Text="{my:ValidationBinding Path=Text}" />

As an example, I have exposed the Binding’s Path property, but you actually have to do this for all of the public properties in Binding. A reference of all the properties that should be implemented can be found here.

ProvideValue returns the result of the Binding’s ProvideValue function, but first it checks whether the binding target has finished loading. If it has already finished loading then it forces validation by calling UpdateSource() on the target. In the much more likely scenario that the control has not yet loaded (this will be the case when you set your binding in XAML) it attaches a handler to the Loaded event so that the ForceValidation subroutine can be deferred until it is finished loading.

Also, notice that I set both ValidatesOnDataErrors and ValidatesOnExceptions to True in the constructor so that I didn’t need to specify it in the XAML. Chances are that whenever you use this markup extension you will want those enabled anyways.

It may seem like a lot of work, but it is a very reusable solution that gives you significantly more power.

Manipulating automatically generated LINQ to SQL classes

There are a few problems with the data model code that is automatically generated in LINQ to SQL. The most obvious issues are that class names are not capitalized and that tables with two foreign keys to the same table will not have descriptive names. For example, if a table has columns firstUserID and secondUserID which are both foreign keys to the users table then you would probably hope to see the properties FirstUser and SecondUser on that class. Unfortunately, what you will actually get is User and User1 which is pretty much pointless because it is very difficult to tell which one is which. One way to tackle this is to simply change the code after it has been generated so that it looks like you want it to. But then as soon as you change the database and import the model again your changes are lost and have to be redone every time. Ideally, the automatically generated code would be formatted exactly as you want it.

The solution I came up with was to useĀ SqlMetal to generate XML output, then manipulate that output and feed it back into SqlMetal so that it can generate the code from the altered XML. As a naming heuristic, I specified that a foreign key column’s property would have a name derived from the column name without the “ID” suffix and a capitalized first letter. Depending on the extent of the changes you plan on making, you may want to make an XSLT file to translate the XML, or simply use some regular expressions.

One downside to this approach is that SqlMetal often cannot generate code for stored procedures because it is unable to determine the return type without actually running the procedure. To get around this I told SqlMetal not to generate any code for the stored procedures (just omit the /sprocs argument), then manually incorporated the XML for my stored procedures in the XSLT file so that it would be injected into the second input to SqlMetal that actually generates the code.

Discard changes in LINQ to SQL DataContext

The LINQ to SQL DataContext provides excellent functionality for managing a set of local changes to a database that can be pushed to the server with a single call to SubmitChanges(). Inevitably there will be situations where you want to discard the changes you have made, effectively allowing you to continue using the DataContext as though those changes had never been made. Unfortunately, there is no DataContext.DiscardChanges() method.

A little research reveals that this is by design and that you should simply recreate the DataContext in these cases, but of course, nothing is that simple. Every object you have that came from the original DataContext now needs to be reset to use the new one to guarantee predictable behaviour. For example, the last line of this snippet will set objectsAreEqual to False:

' Create two data contexts
Dim dc1 As New UsersDataContext
Dim dc2 As New UsersDataContext
 
' Grab the same record out of both the data contexts
Dim user1 = dc1.Users.First
Dim user2 = dc2.Users.First
 
' False, because the otherwise identical records come from different contexts
Dim objectsAreEqual = user1 = user2

Basically, this shows that it does matter where your object came from. If you just want to discard a few little changes and you don’t want to have to recreate all your variables, you can instead undo all the changes that you have made so far and continue to use the same DataContext.

Undoing inserts and deletes is easy, because we can just do the opposite to revert the change. Luckily there is even a nice function on the DataContext that will show us what we need to do called GetChangeSet:

Public Sub DiscardInsertsAndDeletes(ByVal data As DataContext)
    ' Get the changes
    Dim changes = data.GetChangeSet()
 
    ' Delete the insertions
    For Each insertion In changes.Inserts
        data.GetTable(insertion.GetType).DeleteOnSubmit(insertion)
    Next
 
    ' Insert the deletions
    For Each deletion In changes.Deletes
        data.GetTable(deletion.GetType).InsertOnSubmit(deletion)
    Next
End Sub

LINQ to SQL is smart enough to know that if a row is inserted and then deleted (or the other way around) nothing needs to be done. If you look at the ChangeSet after running this function, you will notice that the Inserts and Deletes collections are empty. Updates are a little more annoying. If you update a value, and then set it back to its original state then you will get the expected behaviour (ie: the ChangeSet will be empty because you reverted your change) but unless you write code to keep track of the original value yourself, there is no way to automatically put an object back into its start state without hitting the database. If hitting the database is acceptable, you can always use the Refresh function to get rid of the updates:

Public Sub DiscardUpdates(ByVal data As DataContext)
    ' Get the changes
    Dim changes = data.GetChangeSet()
 
    ' Refresh the tables with updates
    Dim updatedTables As New List(Of ITable)
    For Each update In changes.Updates
        Dim tbl = data.GetTable(update.GetType)
        ' Make sure not to refresh the same table twice
        If updatedTables.Contains(tbl) Then
            Continue For
        Else
            updatedTables.Add(tbl)
            data.Refresh(RefreshMode.OverwriteCurrentValues, tbl)
        End If
    Next
End Sub