Single instance WPF application in C#

Keeping in the same vein as my previous post, I frequently find that I have to solve the same problems at times. After a year or several months I usually move onto another project, consequently no longer have the source code, so I am posting this as a bit of a sticky as I am sure someone will find it useful.

Visual Basic has single instance classes one can use, one can import these into any C# application and consume them (that, after all,  is the real beauty of .NET), but I found that there was too much code, and too many classes, and it was taking me too long a little while back. I solve this problem using the Process class. Create a WPF application and use as follows;

using System.Diagnostics;
using System.Linq;
using System.Windows;
 
namespace SingleInstanceApp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
IsAppAlreadyRunning();
}
 
private static void IsAppAlreadyRunning()
{
Process currentProcess = Process.GetCurrentProcess();
 
if (Process.GetProcessesByName(currentProcess.ProcessName).Any(p => p.Id != currentProcess.Id))
{
MessageBox.Show("Another instance is already running.", "Application already running",
MessageBoxButton.OK, MessageBoxImage.Exclamation);
Current.Shutdown();
return;
}
}
}
}

Copying an object in C# and Visual Basic

Sometimes there are classes you find you use in every project. I remember once (shudder) I, rather inelegantly instantiated a class, and performed a manual copy of all the properties in the object (when the pressure was on, and I just needed to make the thing work).

I have also found myself spending hours chasing subtle and hard to debug issues where ICloneable has been used -  which, incidentally, is widely accepted as an interface one ought never use – or Object.MemberwiseClone. It turns out the only way to do this correctly, is to serialise the object, and then use the deserialised object, implemented here using an extension method.

Even though this is quite straightforward, I still am posting this however , because I find I need to use this functionality frequently, and often I no longer have access to the source, or it takes ages to find the class. The Visual Basic code sample is after the C# one.

C#

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
 
namespace ObjectCopierApp.Extensions
{
/// <summary>
/// Provides a method for performing deep copying of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
internal static class ObjectCopier
{
/// <summary>
/// Perform a deep copy of an object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
internal static T Clone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
 
// Don’t serialize a null object, simply return the default for that object
if (ReferenceEquals(source, null))
{
return default(T);
}
 
IFormatter formatter = new BinaryFormatter();
 
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
}
 
 

Visual Basic

Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
 
Namespace ObjectCopierApp.Extensions
”’ <summary>
”’ Provides a method for performing deep copying of an object.
”’ Binary Serialization is used to perform the copy.
”’ </summary>
Friend NotInheritable Class ObjectCopier
Private Sub New()
End Sub
”’ <summary>
”’ Perform a deep copy of an object.
”’ </summary>
”’ <typeparam name="T">The type of object being copied.</typeparam>
”’ <param name="source">The object instance to copy.</param>
”’ <returns>The copied object.</returns>
<System.Runtime.CompilerServices.Extension()> _
Friend Shared Function Clone(Of T)(source As T) As T
If Not GetType(T).IsSerializable Then
Throw New ArgumentException("The type must be serializable.", "source")
End If
 
‘ Don’t serialize a null object, simply return the default for that object
If ReferenceEquals(source, Nothing) Then
Return Nothing
End If
 
Dim formatter As IFormatter = New BinaryFormatter()
 
Using stream = New MemoryStream()
formatter.Serialize(stream, source)
stream.Seek(0, SeekOrigin.Begin)
Return DirectCast(formatter.Deserialize(stream), T)
End Using
End Function
End Class
End Namespace

ItemsControl Performance Improvements in .NET 4.5

WPF is Slow

One of the most common complaints from C++ or Windows Forms developers moving to WPF/XAML is the issue of performance. I have worked exclusively and intricately with WPF/XAML for the last 4 years and at times have come across performance issues that put me in a corner, including;

  • I needed to enumerate all the alarm and safety devices in an Airports security system inventory. This included fire, smoke, travelator, escalator, motion detection etc. in effect I needed to load up thousands of hardware devices into the WPF application for configuration
  • I was dealing with scientific data for DNA, RNA and Protein. Typically you would have an image with an electropherogram attached to it, which contains thousands of points of floating point data. Scientists required the ability to step through several different samples quickly in order to perform analysis on this data.
    In both these applications, I ended up having to make significant compromises, including using a Windows Forms chart in the scientific application as loading thousands of floating point data into the plethora of commercial and open source WPF charts we tried was unbearably slow. The Windows Forms chart would render the data in milliseconds, where WPF would take a minimum of 10 or 20 seconds with the same data-set, and given the fact that we needed to extend the chart with additional functionality, it added several months worth of development to alter the Windows Forms chart, where it would have been far easier and less time consuming using WPF.

    Staggering

    It turns out that peoples cries about the sluggish nature of WPF applications are correct. Microsoft have managed to attain simply staggering performance improvements to the ItemsControl in WPF. An ItemsControl represents a control that can be used to present a collection of items. In WPF, this includes the TreeView, ListBox, ListView and DataGrid controls that are built using ItemsControls.

DotNet4

In .NET 4 (Visual Studio 2010) and previous, a test was conducted where 12 000 items are loaded into an ItemsControl, the results are in the image below

OutOfMemory

After about 7 minutes, the computer throws an out of memory exception, which I am sure you will agree is absolutely terrible. Microsoft prioritised this issue and in the first iteration managed to increase the total number of items loaded to 200 000 (from 12 000) and load these in 24.5 seconds, an incredible improvement.

FirstIteration

The Pièce de résistance is that they continued to try and get this already considerable metric down even further, in the end  they got this down to 2.3 seconds.

Final

If you have a WPF application that is data centric, especially handling thousands of rows of data, then upgrading to .NET 4.5 is an absolute no brainer. WPF is now at least 182 times quicker whilst handling 16 times more data.

It means that WPF is going to be significantly faster with the additional improvements that have been made to virtualisation in ItemsControls and Cold/Warm start-up times for .NET applications in general.

Calculate range/limit with C#

A recurring requirement in every day programming is determining whether a value exists with a certain range. Since it is exam time (for most students at present), I resolved to write a quick application demonstrating this requirement based around examination marks.

This quick demo is written in WPF, but should work in Silverlight or Windows Phone 7 with no alteration. The Range class though, can be used throughout .NET in general.

To start with, create a new WPF application in visual Studio and call it ExamApp. Add a new folder to the project called Range and in this declare a new interface called IRange with the following members

using System;
 
namespace ExamApp.Range
{
public interface IRange<T> where T : IComparable<T>
{
T Start { get; }
T End { get; }
bool InRange(T valueToFind);
}
}

Create a new class in the same folder called Range which implements the interface above

using System;
 
namespace ExamApp.Range
{
public class Range<T> : IRange<T> where T : IComparable<T>
{
private readonly T start;
private readonly T end;
 
public Range(T start, T end)
{
if (start.CompareTo(end) <= 0)
{
this.start = start;
this.end = end;
}
else
{
this.start = end;
this.end = start;
}
}
 
public T Start
{
get { return this.start; }
}
 
public T End
{
get { return this.end; }
}
 
public bool InRange(T valueToFind)
{
return valueToFind.CompareTo(Start) >= 0 && valueToFind.CompareTo(End) <= 0;
}
}
}
 

Add a new Folder to the project called Examinations and in this add a new class called Percentage. This Percentage class inherits off Range, and here you can create whatever logical range class you may desire for your own applications

using System;

using ExamApp.Range;
 
namespace ExamApp.Examinations
{
public class Percentage<T> : Range<T> where T : IComparable<T>
{
public Percentage(T start, T end) : base(start, end)
{
}
}
}
 

Add a new enumeration called Grade thus

namespace ExamApp.Examinations

{
public enum Grade
{
None = 0,
A = 1,
B = 2,
C = 3,
D = 4,
E = 5,
} ;
}
 

Add a new interface called ITest with the following members.

namespace ExamApp.Examinations

{
interface ITest
{
int ArtAndDesignMark { get; set; }
int ScienceMark { get; set; }
int MathsMark { get; set; }
}
}
 

Add a new folder called Converters to the project, and add the following

using System;

using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Data;
using System.Windows.Markup;
using ExamApp.Examinations;
 
namespace ExamApp.Converters
{
public class MarkToGradeConverter : MarkupExtension, IValueConverter
{
private static MarkToGradeConverter instance;
private static readonly Dictionary<Percentage<int>, Grade> Marks;
 
static MarkToGradeConverter()
{
Marks = new Dictionary<Percentage<int>, Grade>
{
{new Percentage<int>(80, 100), Grade.A},
{new Percentage<int>(75, 79), Grade.B},
{new Percentage<int>(60, 74), Grade.C},
{new Percentage<int>(55, 59), Grade.D},
{new Percentage<int>(0, 54), Grade.E},
};
}
 
public override object ProvideValue(IServiceProvider serviceProvider)
{
return instance ?? (instance = new MarkToGradeConverter());
}
 
#region Implementation of IValueConverter
 
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return GetGrade((int)value).ToString();
}
 
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
 
public static Grade GetGrade(int mark)
{
Percentage<int> key = Marks.Keys.FirstOrDefault(r => r.InRange(mark));
 
if (key != null)
{
Grade grade;
 
if (Marks.TryGetValue(key, out grade))
{
return grade;
}
}
return Grade.None;
}
 
#endregion
}
}
 

As you can see most of the logic is executed here. Add a new class to the project called Student with the following properties. Also note that this implements the ITest interface that was declared earlier

using ExamApp.Examinations;

 
namespace ExamApp
{
public class Student : ITest
{
public Student(string firstName, string surname, int artAndDesignMark, int scienceMark, int mathsMark)
{
this.FirstName = firstName;
this.Surname = surname;
this.ArtAndDesignMark = artAndDesignMark;
this.ScienceMark = scienceMark;
this.MathsMark = mathsMark;
}
 
public Student()
{
}
 
public string FirstName { get; set; }
public string Surname { get; set; }
 
#region Implementation of ITest
 
public int ArtAndDesignMark { get; set; }
public int ScienceMark { get; set; }
public int MathsMark { get; set; }
 
#endregion
 
}
}
 

We need a collection of students to show in a list so create the following class that inherits off ObservableCollection<T>

using System.Collections.ObjectModel;

namespace ExamApp
{
public class Students : ObservableCollection<Student>
{
public Students()
{
Add(new Student
{
FirstName = "John",
Surname = "Lennon",
ArtAndDesignMark = 81,
ScienceMark = 59,
MathsMark = 77
});
Add(new Student
{
FirstName = "Paul",
Surname = "McCartney",
ArtAndDesignMark = 88,
ScienceMark = 40,
MathsMark = 66
});
Add(new Student
{
FirstName = "Ringo",
Surname = "Starr",
ArtAndDesignMark = 88,
ScienceMark = 31,
MathsMark = 96
});
Add(new Student
{
FirstName = "George",
Surname = "Harrison",
ArtAndDesignMark = 100,
ScienceMark = 99,
MathsMark = 99
});
 
}
}
}
 

Now the data structures are complete, add the following .xaml markup

<Window x:Class="ExamApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Converters="clr-namespace:ExamApp.Converters"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<Converters:MarkToGradeConverter x:Key="MarkToGradeConverter" />
</Window.Resources>
<ListView x:Name="studentsListBox">
<ListView.View>
<GridView>
<GridViewColumn Width="120"
DisplayMemberBinding="{Binding Path=FirstName}"
Header="Name" />
<GridViewColumn Width="120"
DisplayMemberBinding="{Binding Path=Surname}"
Header="Surname" />
<GridViewColumn Width="40"
DisplayMemberBinding="{Binding Path=ArtAndDesignMark,
Converter={StaticResource MarkToGradeConverter}}"
Header="Art" />
<GridViewColumn Width="60"
DisplayMemberBinding="{Binding Path=ScienceMark,
Converter={StaticResource MarkToGradeConverter}}"
Header="Science" />
<GridViewColumn Width="50"
DisplayMemberBinding="{Binding Path=MathsMark,
Converter={StaticResource MarkToGradeConverter}}"
Header="Maths" />
</GridView>
</ListView.View>
 
</ListView>
 
</Window>
 

Add the following code to the constructor of the main window

using System.Windows;
 
namespace ExamApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.studentsListBox.ItemsSource = new Students();
}
}
}
 

You should have the following

Students

As you can see it is quite a simple and pretty reusable way to use ranges in your application.

The source code for this simple example is available here

Zoomable autosizing canvas in WPF

I have created a control for a project I am working on that uses a canvas to draw graph ticks for a custom scale, but ran into the limitation of the canvas control where child items are not scaled accordingly when the height (or width) of the canvas changes. Luckily, this is quite a straightforward problem to fix, but I just could not seem to find either the correct search terms to enter in Google or locating code samples in books that demonstrated how to resolve the issue. I have just knocked this code up this afternoon so it is not perfect, but should suffice should you require something similar.

Small

Large

In order to resolve the problem you will need to create a custom canvas and override both MeasureOverride and ArrangeOveride incorporating any custom logic you require in these methods.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
 
namespace AutosizingCanvasApp.Controls
{
public class TickCanvas : Canvas
{
// Vertical axis where the X value is never changed
private const double X = 0;
private Size initialSize;
 
// Override the default Measure method of Panel
protected override Size MeasureOverride(Size availableSize)
{
var canvasDesiredSize = new Size();
 
// In our example, we just have one child.
// Report that our canvas requires just the size of its only child.
 
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
canvasDesiredSize = child.DesiredSize;
}
 
return canvasDesiredSize;
}
 
protected override Size ArrangeOverride(Size finalSize)
{
if (initialSize.Height == 0)
{
initialSize = finalSize;
}
var ratio = finalSize.Height / initialSize.Height;
 
for (int index = 0; index < this.InternalChildren.Count; index++)
{
UIElement child = this.InternalChildren[index];
 
double y = ((Line)child).Y1;
 
child.Arrange(finalSize.Height > initialSize.Height
? new Rect(new Point(X, (ratio * y) – y), child.DesiredSize)
: new Rect(new Point(X, 0), child.DesiredSize));
}
return finalSize; // Returns the final Arranged size
}
}
}

In the .xaml I have a border with the custom canvas as a child that have some Line objects all affecting the Y axis position.

<Window x:Class="AutosizingCanvasApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:AutosizingCanvasApp.Controls"
xmlns:local="clr-namespace:AutosizingCanvasApp.Converters"
Title="mainWindow"
Width="300"
Height="768"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<local:BorderHeightValueConverter x:Key="BorderHeightValueConverter" />
<local:LinePositionConverter x:Key="LinePositionConverter" />
</Window.Resources>
 
<Border x:Name="mainBorder"
Width="94"
Height="{Binding ElementName=mainWindow,
Path=ActualHeight,
Converter={StaticResource BorderHeightValueConverter}}"
Margin="50"
BorderBrush="Black"
BorderThickness="2"
ToolTip="{Binding ElementName=mainBorder,
Path=ActualHeight}">
<controls:TickCanvas x:Name="myCanvas">
<Line x:Name="line1"
Stroke="Red"
StrokeThickness="2"
ToolTip="{Binding ElementName=line1,
Path=Y1}"
X1="0"
X2="60"
Y1="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.2}"
Y2="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.2}" />
<Line x:Name="line2"
Stroke="Blue"
StrokeThickness="2"
ToolTip="{Binding ElementName=line2,
Path=Y1}"
X1="0"
X2="60"
Y1="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.4}"
Y2="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.4}" />
<Line x:Name="line3"
Stroke="Green"
StrokeThickness="2"
ToolTip="{Binding ElementName=line3,
Path=Y1}"
X1="0"
X2="60"
Y1="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.6}"
Y2="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.6}" />
<Line x:Name="line4"
Stroke="Purple"
StrokeThickness="2"
ToolTip="{Binding ElementName=line4,
Path=Y1}"
X1="0"
X2="60"
Y1="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.8}"
Y2="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.8}" />
</controls:TickCanvas>
</Border>
</Window>

I also have a couple of converters that converts the height of the border as that changes when you resize the parent window and a couple of converters that reposition the line objects in the canvas. Be aware that the border itself has a thickness, so you will need to incorporate that in any sizing but has been omitted here so the lines may be a couple of pixels off.

using System;
using System.Globalization;
using System.Windows.Data;
 
namespace AutosizingCanvasApp.Converters
{
public class LinePositionConverter : IValueConverter
{
#region Implementation of IValueConverter
 
/// <summary>
/// Converts a value.
/// </summary>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
/// <param name="value">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((double) value)*double.Parse(parameter.ToString());
}
 
/// <summary>
/// Converts a value.
/// </summary>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
/// <param name="value">The value that is produced by the binding target.</param><param name="targetType">The type to convert to.</param><param name="parameter">The converter parameter to use.</param><param name="culture">The culture to use in the converter.</param>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
 
#endregion
}
}

using System;
using System.Globalization;
using System.Windows.Data;
 
namespace AutosizingCanvasApp.Converters
{
public class BorderHeightValueConverter : IValueConverter
{
#region Implementation of IValueConverter
 
/// <summary>
/// Converts a value.
/// </summary>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
/// <param name="value">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (((double)value)*0.7);
}
 
/// <summary>
/// Converts a value.
/// </summary>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
/// <param name="value">The value that is produced by the binding target.</param><param name="targetType">The type to convert to.</param><param name="parameter">The converter parameter to use.</param><param name="culture">The culture to use in the converter.</param>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
 
#endregion
}
}
 

The source code is for this example is available here.

WPF Message Box

The default MessageBox in WPF looks rather ugly on Windows 7 and Windows Vista

Before

 

Before

After

 

After

In order to update the messagebox, add a new app.manifest file

addManifest

ensure you have the following dependency tag

    1 <?xml version="1.0" encoding="utf-8"?>

    2 <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    3   <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>

    4   <description>iDesign – Media Burner</description>

    5   <dependency>

    6     <dependentAssembly>

    7       <assemblyIdentity name="Microsoft.Windows.Common-Controls" version="6.0.0.0" type="win32" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />

    8     </dependentAssembly>

    9   </dependency>

   10   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">

   11     <security>

   12       <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">

   13         <!– UAC Manifest Options

   14             If you want to change the Windows User Account Control level replace the

   15             requestedExecutionLevel node with one of the following.

   16 

   17         <requestedExecutionLevel  level="asInvoker" uiAccess="false" />

   18         <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />

   19         <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

   20 

   21             Specifying requestedExecutionLevel node will disable file and registry virtualization.

   22             If you want to utilize File and Registry Virtualization for backward

   23             compatibility then delete the requestedExecutionLevel node.

   24         –>

   25         <requestedExecutionLevel level="asInvoker" uiAccess="false" />

   26       </requestedPrivileges>

   27     </security>

   28   </trustInfo>

   29 

   30   <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">

   31     <application>

   32       <!– A list of all Windows versions that this application is designed to work with. Windows will automatically select the most compatible environment.–>

   33 

   34       <!– If your application is designed to work with Windows 7, uncomment the following supportedOS node–>

   35       <!–<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>–>

   36 

   37     </application>

   38   </compatibility>

   39 

   40   <!– Enable themes for Windows common controls and dialogs (Windows XP and later) –>

   41   <!– <dependency>

   42     <dependentAssembly>

   43       <assemblyIdentity

   44           type="win32"

   45           name="Microsoft.Windows.Common-Controls"

   46           version="6.0.0.0"

   47           processorArchitecture="*"

   48           publicKeyToken="6595b64144ccf1df"

   49           language="*"

   50         />

   51     </dependentAssembly>

   52   </dependency>–>

   53 

   54 </asmv1:assembly>

   55 

Burning and Erasing CD/DVD/Blu-ray Media with WPF

Some time ago I worked on a project where I needed a DVD burner/formatter, and came across an open source version by Eric Haddan. The only problem with that excellent solution was that it was written in winforms ,and I was working on a WPF application. I have now ported that application to WPF using MVVM.

burneru

You can download the free WPF burner at http://wpfburner.codeplex.com/. Just select the downloads tab and save the source code.

If you are on XP then you will need Image Mastering API v2.0 (IMAPIv2.0) for Windows XP if you don’t have this already (this is included in Vista SP2 and Windows 7). To burn a Blu-ray you will need Windows Feature Pack for Storage 1.0 if you are not using Window 7.

Common sense lost with MVVM

I am a big fan of using MVVM in WPF applications, but am finding, increasingly,  that even seasoned developers frequently dispose of very good habits, in order to stay true to the pattern.

One such occurrence is is not using message boxes. A  cardinal sin in MVVM, is ensuring that message boxes are never used in View Models. The end result is that one starts to see code like this.

delete

If you don’t have a logging system for your exceptions then you should have, if you do then always ensure that you log the exception. During development, one instinctually starts to determine brittle code, and events where errors can occur and use try-catch blocks. The worst thing you can do here is nothing. It is better not to use the try-catch at all, and just let the application blow-up, because at least you know that there is a problem, and go about fixing it.

I really cannot sufficiently impress upon thee just how much of a bad practice this is, and the amount of time you or other developers that work on your project will spend trying to find obscure bugs that occur because you are swallowing exceptions, just because MVVM stipulates that message boxes should not be used, means they shouldn’t, they should!

Free WPF Ribbon with source code and MVVM samples

Finally after about 2 years as a CTP, Microsoft have released the WPF ribbon. Due to the delay, one can be certain that they were allowing their third party software vendors as much traction for users that needed a ribbon, but some brilliant open source versions including Fluent Ribbon Control Suite have been developed.

ribbon

The best thing about the release, is that the Office Fluent UI licensing is now no longer a requirement. This allows people to download the software straight away, without having to go through the cumbersome process of logging into the Office website, signing the licensing, then spending half a day trying to locate the installation because it was hidden in a way that made you think they don’t want anyone to use it.

The download for the ribbon is available here. Please ensure that you also take the time to install the source and samples if you want to build MVVM compliant applications with the ribbon (you should be doing this in WPF anyway) . The MSDN documentation is available here.

The installation notes say that this is not supported on XP, but on vista upwards but I have not tested this. If there are issues then you should be able to use another vendor.

After installing the MSI you should have the following template in Visual Studio

project

There is no information on the installation templates for the express editions, but I would hazard a guess as to them never being available, as building applications with a Ribbon is not something a learner ‘typically’ does. If you are using express, then you should be able to add the requisite .dll thus. If you look in my Tree View below in Visual Studio, you will find that there is a reference to RibbonControlsLibrary. This is located at; C:\Program Files (x86)\Microsoft Ribbon for WPF\v3.5.40729.1\RibbonControlsLibrary.dll

tree

Note:  If you installed the source and samples as well, a .zip file with both is available at the same location. Copy this, and unzip it in a location of your choosing

source

The code behind for my window has the following code, so inherit off RibbonWindow

ribboncode

Finally your XAML should be defined so, and you’re good to go!

xaml

WPF and Silverlight Timer

Users of Windows Forms will know that there are three timer objects you can use, namely the Windows Forms Timer, the System Timers Timer and finally the System Threading Timer, as the following example demonstrates;

Note: this tutorial is in both C# and Visual Basic, so look beneath the Visual Basic examples for the C# Version.

Visual Basic

Public Class Form1

 

    Dim timerCallBack As System.Threading.TimerCallback

 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ”Winforms Timer

        Dim wfTimer As System.Windows.Forms.Timer()

 

        ”Timers Timer

        Dim tTimer As System.Timers.Timer()

 

        ”Threading Timer

        timerCallBack = AddressOf PrintTime

        Dim thTimer As System.Threading.Timer = New System.Threading.Timer(Me.timerCallBack)

 

 

    End Sub

 

    Private Sub PrintTime(ByVal obj As System.Object)

        ”Print the time to screen

    End Sub

 

 

End Class

C#

using System.Windows.Forms;

 

namespace TimersExample

{

    public partial class Form1 : Form

    {

        System.Threading.TimerCallback timerCallBack;

 

        public Form1()

        {           

            InitializeComponent();

        }

        private void Form1_Load(object sender, System.EventArgs e)

        {

            // Winforms Timer

            System.Windows.Forms.Timer wfTimer = new Timer();

 

            //Timers Timer

            System.Timers.Timer tTimer = new System.Timers.Timer();

 

            //Threading Timer

            timerCallBack = new System.Threading.TimerCallback(PrintTime);

            System.Threading.Timer thTimer = new System.Threading.Timer(this.timerCallBack);

        }

        private void PrintTime(object obj)

        {

            //Print the time to screen

        }

 

    }

}

 

In both WPF and Silverlight there is a new timer (the fourth .NET framework timer) called the System.Windows.Threading.DispatcherTimer. To demonstrate how this works, look at the following simple code sample. In it, there is some XAML that declares a label, button and a button click and window loaded events (In Silverlight use the UserControl_Loaded event for the page instead of Window_Loaded).

 

<Window x:Class="WpfTimer.Window1"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">

    <Grid>

 

        <StackPanel Orientation="Vertical">

        <Label Height="28" Width="70" Name="label1">Label</Label>

        <Button Height="23" Width="70" Name="button1" Click="button_Click">Button</Button>

 

        </StackPanel>

 

    </Grid>

</Window>

 

Note that in the Visual Basic XAML you have Window x:Class="Window1" at the top (in case you’re wondering why the XAML does not compile). In the code behind, you have the following code that instantiates a DispatcherTimer in the load event of the Window, and allows a user from starting and stopping the timer by toggling the button click event.

   

Visual Basic

Class Window1

    Dim timer As System.Windows.Threading.DispatcherTimer

    Public Event UpdateTime()

 

    Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)

        timer = New System.Windows.Threading.DispatcherTimer()

        timer.Interval = TimeSpan.FromSeconds(1)

        AddHandler timer.Tick, AddressOf timer_Tick

 

    End Sub

 

    Sub timer_Tick(ByVal sender As Object, ByVal e As EventArgs)

        Me.label1.Content = DateTime.Now.ToLongTimeString()

    End Sub

 

    Private Sub button1_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)

        If Not Me.timer.IsEnabled Then

            Me.timer.Start()

            Me.button1.Content = "Stop"

        Else

            Me.timer.[Stop]()

            Me.button1.Content = "Start"

        End If

    End Sub

 

 

 

 

End Class

 

C#

using System;

using System.Windows;

 

namespace WpfTimer

{

    /// <summary>

    /// Interaction logic for Window1.xaml

    /// </summary>

    public partial class Window1 : Window

    {

        System.Windows.Threading.DispatcherTimer timer;

 

        public Window1()

        {

            InitializeComponent();         

        }

        private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            timer = new System.Windows.Threading.DispatcherTimer();

            timer.Interval = TimeSpan.FromSeconds(1);

            timer.Tick += new EventHandler(timer_Tick);

        }

 

        void timer_Tick(object sender, EventArgs e)

        {

            this.label1.Content = DateTime.Now.ToLongTimeString();

        }

 

        private void button_Click(object sender, RoutedEventArgs e)

        {

            if (!this.timer.IsEnabled)

            {

                this.timer.Start();

                this.button1.Content = "Stop";

            }

            else

            {

                this.timer.Stop();

                this.button1.Content = "Start";

            }

        }

 

 

    }

}

 

DispatcherTimer

Follow

Get every new post delivered to your Inbox.