Pages

Wednesday 10 December 2008

Universe SEQ function and .Net

Not really a WPF issue but I don't want to lose track of this reference.

This blog has lots of useful info regarding using Universe from .Net
GigaMegaTech
including this nugget about the SEQ() function.

The strings returned from Universe are encoded in ANSI format. So the SEQ function in Universe doesn't return the same values in the extended character set as .Net does. Therefore the need to use:

Encoding.Ansi.GetBytes();

Wednesday 26 November 2008

WCF and Custom Exceptions

From within the Server we throw custom exceptions which contain custom data that the client code can use. To transport these across WCF to the client we wrap them in a FaultException like this:
catch (BlockBookingInvalidFloorsException ex)
{
throw new FaultException(ex);
}
Despite the fact that both the custom exception and the contained classes are marked as [Serializable()] it results in a WCF CommunicationException.

To resolve this we now add this new constructor:
public BlockBookingInvalidFloorsException(SerializationInfo serializationInfo, StreamingContext streamingContext)
: base(serializationInfo, streamingContext) { }
Martin found this blog with a fuller explanation: WCF and Custom Exceptions

Claus suggests that custom exceptions should derive from either CommunicationException or System.Exception. Our's derive from ApplicationException with no problem, indeed the ApplicationException already includes this constructor (protected).

Sub Classing Window and UserControl

I wanted to add a standard method (InjectModel) into our Windows and UserControls and the obvious technique was to subclass them with something like this:
public partial class PersonEditView : WindowBase
{
...
}

public class WindowBase : Window
{
...
}
The xaml then needs to reference the WindowBase class like this:
<local:WindowBase x:Class="INPC2.PersonEditView"
...
xmlns:local="clr-namespace:INPC2"
>
<local:WindowBase.Resources>
...
</local:WindowBase.Resources>
...
</local:WindowBase>
There is no problem with the forward reference to xmlns:local

ObjectDataProvider

To make UI design easier in Blend we want to provide dummy data at design time. Using an ObjectDataProvider with an ObjectType attribute achieves this (provided the bound datasource can provide dummy data).

<ObjectDataProvider x:Key="DesignTimeDataProvider" d:IsDataSource="True" ObjectType="{x:Type Dummy_Application:PeopleDataProvider}"/>
However it is not possible to replace the ObjectType with an ObjectInstance at runtime.
We got round that problem by using two ObjectDataProviders:
<ObjectDataProvider x:Key="DesignTimeDataProvider" d:IsDataSource="True" ObjectType="{x:Type Dummy_Application:PeopleDataProvider}"/>
<ObjectDataProvider x:Key="InnerDataProvider" d:IsDataSource="true" ObjectInstance="{StaticResource DesignTimeDataProvider}"/>
<ListBox ItemsSource="{Binding Path=DataProvider.PeopleList, Source={StaticResource InnerDataProvider}}"/>
Then in the code behind we replace the ObjectInstance with our freshly minted data source:
ObjectDataProvider odpWindow = (ObjectDataProvider)this.FindResource("InnerDataProvider");
odpWindow.ObjectInstance= newPeopleDataProvider;
The problem with this approach is that at runtime a datasource is created (as part of InitializeComponent) that is then immediately discarded.

To resolve this I created my own ObjectDataProvider which nulls the ObjectType at runtime. This is enough to allow the ODP to accept a change to the ObjectInstance without complaint.
public class MyObjectDataProvider : ObjectDataProvider
{
bool isInDesignMode = (bool)DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue;
public new Type ObjectType
{
get { return base.ObjectType; }
set
{
if (!isInDesignMode) value = null;
base.ObjectType = value;
}
}
}

public partial class PersonEditView : Window
{
public PersonEditView()
{
InitializeComponent();
((ObjectDataProvider)this.FindResource("DataModel")).ObjectInstance = model; }
}
The xaml then becomes simpler and cleaner:
<local:MyObjectDataProvider x:Key="DataModel" d:IsDataSource="True" ObjectType="{x:Type local:PersonEditModel}" />
<TextBlock Text="{Binding Source={StaticResource DataModel}, Path=APerson.Surname}"/>

INotifyPropertyChanged

I had a conversation with Martin about INotifyPropertyChanged and it made me realise there was an (other) aspect of Binding that I hadn't appreciated.

So I created a little project to test my assumptions.

1) Business Class implements INotifyPropertyChanged

public class Person : INotifyPropertyChanged
{
private string _surname = "";
public string Surname
{
get { return _surname; }
set
{
_surname = value;
OnPropertyChanged("Surname");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
2) Model exposing two instances of Person. Model does not implement INPC

public class Model
{
public Person APerson { get; set; }
public Person AnotherPerson { get; set; }
public Model()
{
APerson = new Person();
AnotherPerson = new Person();
}
}
3) Bind to only one of the two instances of Person in the Model

<TextBlock Text="{Binding Model.APerson.Surname}"></TextBlock>
<Button Click="Button_Click">Go</Button>
4) Wire it all up

public partial class Window2 : Window
{
private Model _model = new Model();
public Model Model
{
get { return _model; }
set { _model = value; }
}
public Window2()
{
InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Model.APerson.Surname = "Smith";
Model.AnotherPerson.Surname = "Jones";
}
}
Result:
PropertyChanged is only hooked up for APerson and not for AnotherPerson because nothing is bound to AnotherPerson in the xaml.

Conclusion:
I might need to revisit the changes I made to AbstractModel hooking up PropertyChanged and DataError. Currently they are hooked up when the Model is instantiated, regardless of whether there is any binding in the xaml.

Quiz - guess the technology

Jeremiah says:
I've been vocal at work about how stupid I think xxxxxx is.

Mike says:
Why is it stupid?

Jeremiah says:
Because it looks snazzy 4 seconds after you've put in a feature but then 4 months later it still isn't quite right; takes forever to make minor tweaks; doesn't have anything to offer over simple HTML (other than the RAD) but has less features.

Wednesday 19 November 2008

Custom Control Part 2

In "Custom Control Part 1" we created a raw custom control that does nothing. In this post we'll change the control so it only does "one thing" - stores its original value and when the current value differs it sets the HasChanged property to true.

This needs a couple of private member vars (OldText & Initialised) to hold the state, a new DependencyProperty (HasChangedProperty), a standard CLR property (HasChanged) and some logic added to the TextPropertyChanged event handler.

public class DemoTextBox : TextBox
{
static DemoTextBox()
{
// Create a callback for when the TextProperty changes
PropertyChangedCallback callback = new PropertyChangedCallback(TextPropertyChanged);

// Override the TextProperty metadata in order to link up the callback routine
TextProperty.OverrideMetadata(
typeof(DemoTextBox),
new FrameworkPropertyMetadata(callback));
}
static void TextPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
// Cast the Sender to an object of this class
DemoTextBox textBox = (DemoTextBox)sender;
 

// Store the OldText value when this event is
// fired for the first time
 
if (!textBox.Initialised)
{
textBox.Initialised = true;
textBox.OldText = textBox.Text;
}

// Set the HasChangedProperty to indicate whether the text has changed

textBox.SetValue(HasChangedProperty, (textBox.OldText != textBox.Text));

 
}

 
private bool Initialised = false;
private string OldText = "";
 
// The new DependencyProperty
 
static readonly DependencyProperty HasChangedProperty = DependencyProperty.Register(
"HasChanged",
typeof(bool),
typeof(DemoTextBox)
);
 
// The new CLR Property
 
public bool HasChanged
{
get { return (bool)GetValue(HasChangedProperty); }
}

}

In the Generic.xaml we'll add a Trigger to turn the textbox background Red when the Text value has changed.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DepProp">
<Style TargetType="{x:Type local:DemoTextBox}">
<Style.Triggers>

<Trigger Property="HasChanged" Value="true">
<Setter Property="Background" Value="Red"/>
</Trigger>

</Style.Triggers>
</Style>
</ResourceDictionary>

Tuesday 18 November 2008

Custom Control Part 1

I've struggled to find a really simple example of creating a custom control. So I created a simple control that did only "one thing" then removed the "one thing" to leave just the very least plumbing that I could.

Starting with a new class that inherits from TextBox:
public class DemoTextBox : TextBox
{
static DemoTextBox()
{
// Create a callback for when the TextProperty changes
PropertyChangedCallback callback = new PropertyChangedCallback(TextPropertyChanged);
// Override the TextProperty metadata in order to link up the callback routine
TextProperty.OverrideMetadata(
typeof(DemoTextBox),
new FrameworkPropertyMetadata(callback));
}
static void TextPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
// Cast the Sender to an object of this class
DemoTextBox textBox = (DemoTextBox)sender;

}
}

Add a ResourceDictionary called Generic.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DepProp>
<Style TargetType="{x:Type local:DemoTextBox}">
<Style.Triggers>
<!-- create a trigger here -->
</Style.Triggers>
</Style>
</ResourceDictionary>

And a reference to the new control in the Window:
<Window x:Class="DepProp.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DepProp"
Title="Window2" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary Source="Generic.xaml"/>
</Window.Resources>
<StackPanel>
<local:DemoTextBox x:Name="TextBoxV1" Text="Original Value" />
</StackPanel>
</Window>

ActiveSharp and StackTrace speed

When implementing the StackTrace within ActiveSharp I did a few tests to check out the speed of the different techniques I could use to get the Property Name.

All the following times are for one million iterations.

TechniqueMilliseconds
ActiveSharp400
StackWalk120000
MethodBase.GetCurrentMethod()2000
"string"20
const string10

The speed of ActiveSharp is a little unrealistic because it caches the Property Name for each field in the class. A class with more properties or accessing many different objects would reduce the speed advantage.

Since the StackWalk was so slow I decided to check whether it was my code (examining the stack) or the creation of the stack in the first instance.
private void Button_Click_2(object sender, RoutedEventArgs e)
{
DateTime start = DateTime.Now;
for (int i = 0; i <= 1000000; i++)
{
StackTrace trace = new StackTrace();
}
DateTime end = DateTime.Now;
MessageBox.Show(end.Subtract(start).TotalMilliseconds.ToString());
}
One million iterations took 118,000 milliseconds to complete. There is little point trying to improve my code further.

MultiBinding

I stumbled across MultiBinding today. I have no immediate use for it but I mustn't forget that it is available.

There is a nice simple example from MSDN here: MultiBinding Class

Monday 17 November 2008

ActiveSharp

ActiveSharp is an excellent piece of free software (ActiveSharp Home Page) written by John Rusk to implement the INotifyPropertyChanged interface.

Since we already have a abstract class that implements INPC I simply used the PropertyMap.GetProperty(this, ref target) method to get the property name and avoid having to hardcode the name as a string in each Property.

I ran into a slight problem because we have some classes that expose the same field in multiple properties (not necessarily the right thing to do but that's what we've got) and ActiveSharp can't deal with this situation.

My proposed solution was to change ActiveSharp to walk the Stack when it encountered these duplicates. John was kind enough to explain the potential pitfalls and the alternative technique of using marking all Properties with this attribute:
[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]

The primary issue is around "inlining" methods when the Release code is built. This can result in fewer entries being available on the stack. Therefore a modified GetProperty might work during development but not live.

I read that there are some situations that prevent inlining:

  • Methods that are greater than 32 bytes of IL will not be inlined.

  • Virtual functions are not inlined.

  • Methods that have complex flow control will not be in-lined. Complex flow control is any flow control other than if/then/else; in this case, switch or while.

  • Methods that contain exception-handling blocks are not inlined, though methods that throw exceptions are still candidates for inlining.

  • If any of the method's formal arguments are structs, the method will not be inlined.

A little experimentation showed that marking the SetValue and GetValue methods in my abstract base class as virtual was enough to get a consistent stack in both Debug and Release versions.

For now this appears to be working OK but I might need to revisit when we move to 64bit Windows Release IS NOT Debug: 64bit Optimizations and C# Method Inlining in Release Build Call Stacks

Important Note:Running the Release version from within the IDE does not give the same results as running the application as a standalone .exe

Speed of Exceptions

I wanted to check for duplicates as entries were being added to my Dictionary collection. I wasn't sure whether to use ContainsKey and check each and every time an item is added or simply sweep up after the Add method throws an Exception.

In reality the best solution will depend on the likely hit rate of duplicates but I thought I'd write the following code to test the speed differential when the hit rate is 100%.

Using ContainsKey
private void Button_Click(object sender, RoutedEventArgs e)
{
DateTime start = DateTime.Now;
for (int i = 0; i <= 1000; i++)
{
if (dummy.ContainsKey("Sunday"))
{
dummy["Sunday"]++;
}
}
DateTime end = DateTime.Now;
MessageBox.Show(end.Subtract(start).TotalMilliseconds.ToString());
}

Using Exceptions
private void Button_Click_1(object sender, RoutedEventArgs e)
{
DateTime start = DateTime.Now;
for (int i = 0; i <= 1000; i++)
{
try
{
dummy.Add("Sunday", 7);
}
catch
{
dummy["Sunday"]++;
}
}
DateTime end = DateTime.Now;
MessageBox.Show(end.Subtract(start).TotalMilliseconds.ToString());
}

Results
Using ContainsKey: 2 milliseconds
Using Exceptions: 5338 milliseconds

The ContainsKey adds about 0.04 milliseconds for the 1000 iterations - the rest is the down to the increment of the Dictionary int value.

Monday 3 November 2008

DelegateCommand vs RoutedCommand vs EventHandler

I wanted to evaluate the difference between using the different types of Command mechanisms. The following code snippets aren't intended to be a working example, they simply highlight the code differences.


DelegateCommand
SimplePresenter.cs

public DelegateCommand<string> GetCustomerByDC { get; private set; }

GetCustomerByDC = new DelegateCommand(ExecuteGetCustomer, CanExecuteGetCustomer);

private void ExecuteGetCustomer(string parameter)
{
try
{
int customerId = int.Parse(parameter);
GetCustomer(customerId);
}
catch { }
}
}
private bool CanExecuteGetCustomer(string parameter)
{
try
{
int customerId = int.Parse(parameter);
return true;
}
catch
{
return false;
}
}

SimpleView.xaml.cs
ObjectDataProvider odpPresenter = (ObjectDataProvider)this.FindResource("MyPresenter");
Presenter = (SimplePresenter)odpPresenter.ObjectInstance;
Presenter.Model = newModel as SimpleModel;
Presenter.View = this;
private void txtCustomerId_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
Presenter.GetCustomerByDC.RaiseCanExecuteChanged();
}

SimpleView.xaml

xmlns:Presenters="clr-namespace:Sandstorm.Documents.Patterns.Presenters"
<ObjectDataProvider x:Key="MyPresenter" d:IsDataSource="True" ObjectType="{x:Type Presenters:SimplePresenter}"/>
<Button
x:Name="btnGetByDC"
Command="{Binding Source={StaticResource MyPresenter}, Path=GetCustomerByDC}"
CommandParameter="{Binding ElementName=txtCustomerId, Path=Text}"
Width="170"
>Get By DelegateCommand</Button>
<TextBox
TextChanged="txtCustomerId_TextChanged"
/>

RoutedCommand

SimpleView.xaml.cs
private void GetCustomer_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
if (e.Parameter != null)
{
try
{
int customerId = int.Parse(e.Parameter as string);
Presenter.GetCustomer(customerId);
}
catch { }
}
}
private void GetCustomer_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
{
try
{
int customerId = int.Parse(e.Parameter as string);
e.CanExecute = true;
}
catch
{
e.CanExecute = false;
}
}

SimpleView.xaml
<UserControl.CommandBindings>
<CommandBinding
Command="local:LeisureCommands.GetCustomerCommand"
Executed="GetCustomer_Executed"
CanExecute="GetCustomer_CanExecute"
/>
</UserControl.CommandBindings>
<Button
x:Name="btnGetByRC"
Command="local:LeisureCommands.GetCustomerCommand"
CommandParameter="{Binding ElementName=txtCustomerId, Path=Text}"
Width="170"
>Get By Routed Command</Button>

LeisureCommands.cs
public class LeisureCommands : RoutedUICommand
{
public readonly static RoutedUICommand GetCustomerCommand;
static LeisureCommands()
{
GetCustomerCommand = new RoutedUICommand("Get Customer...", "GetCustomerCommand", typeof(LeisureCommands));
GetCustomerCommand.InputGestures.Add(new KeyGesture(Key.C, ModifierKeys.Alt));
}
}



Event
SimpleView.xaml.cs
private void btnGetByClick_Click(object sender, RoutedEventArgs e)
{
try
{
int customerId = int.Parse(txtCustomerId.Text);
Presenter.GetCustomer(customerId);
}
catch { }
}

SimpleView.xaml
<Button
x:Name="btnGetByClick"
Click="btnGetByClick_Click"
CommandParameter="{Binding ElementName=txtCustomerId, Path=Text}"
Width="170"
>Get By Click Event</Button>


Lines of code
TypeRawOneOffPer CommandCan ExecuteTotal
DelegateCommand406341222
RoutedCommand457381226
Event15015n/a15


Conclusion
The RoutedCommand is a little more expensive in LOC terms than the DelegateCommand but the DelegateCommand does not support all the features of the RoutedCommand, in particular: Gestures.
If the "CanExecute" facility is not required the Event is by far the cheapest / easiest to implement.
I guess my conclusion was: "What are the DelegateCommands bringing to the party?"

Thursday 30 October 2008

Routed Commands

Although we have opted to use the DelegateCommand<T> class in our project, this article gives a good overview of the Command pattern used in WPF.

The Command Pattern In Windows Presentation Foundation

DelegateCommand<T> class implements ICommand rather than subclassing RoutedCommand. The problem with this is that CanExecute is fired only once. RoutedCommands listen to a number of events and fire CanExecute quite frequently.
DelegateCommand<T> offers the RaiseCanExecuteChanged() method which can be fired manually when some "significant" event happens.
Alternatively a timer could be used to call RaiseCanExecuteChanged() at regular intervals. The following code sample uses a DispatcherTimer to raise the event on the UI thread.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_aTimer.Tick += new EventHandler(_aTimer_Tick);
_aTimer.Interval = new TimeSpan(0, 0, 1);
_aTimer.IsEnabled = false;
}

void _aTimer_Tick(object sender, EventArgs e)
{
_model.MyCommand.RaiseCanExecuteChanged();
}


These are the standard supplied commands:
ApplicationCommands—Close, Copy, Cut, Delete, Find, Help, New, Open, Paste, Print, PrintPreview, Properties, Redo, Replace, Save, SaveAs, SelectAll, Stop, Undo, and more

ComponentCommands—MoveDown, MoveLeft, MoveRight, MoveUp, ScrollByLine, ScrollPageDown, ScrollPageLeft, ScrollPageRight, ScrollPageUp, SelectToEnd, SelectToHome, SelectToPageDown, SelectToPageUp, and more

MediaCommands—ChannelDown, ChannelUp, DecreaseVolume, FastForward, IncreaseVolume, MuteVolume, NextTrack, Pause, Play, PreviousTrack, Record, Rewind, Select, Stop, and more

NavigationCommands—BrowseBack, BrowseForward, BrowseHome, BrowseStop, Favorites, FirstPage, GoToPage, LastPage, NextPage, PreviousPage, Refresh, Search, Zoom, and more

EditingCommands—AlignCenter, AlignJustify, AlignLeft, AlignRight, CorrectSpellingError, DecreaseFontSize, DecreaseIndentation, EnterLineBreak, EnterParagraphBreak, IgnoreSpellingError, IncreaseFontSize, IncreaseIndentation, MoveDownByLine, MoveDownByPage, MoveDownByParagraph, MoveLeftByCharacter, MoveLeftByWord, MoveRightByCharacter, MoveRightByWord, and more

Tuesday 28 October 2008

DM-V-VM

An interesting series from Dan Crevier's Blog

DataModel-View-ViewModel Pattern Series

Sunday 26 October 2008

Accessing Properties from abstract class

I wanted my abstract class to hook into the PropertyChanged event for any Property in the derived class that implements INotifyPropertyChanged.

I use reflection to get all the properties of the derived class then check that they implement the INotifyPropertyChanged interface before adding the event handler.

The Property must be defined in the "traditional" way rather than using the auto-property syntax otherwise the InitializeProperties method in the abstract class has no object to add the event handlers to.
public class Model : AbstractModel
{
private Till _till = new Till();
public Till Till
{
get { return _till; }
set { _till = value; }
}
}
public abstract class AbstractModel : INotifyPropertyChanged
{
public AbstractModel()
{
InitializeProperties();
}

private void InitializeProperties()
{
PropertyInfo[] propertyInfoList = this.GetType().GetProperties();

foreach (PropertyInfo propertyInfo in propertyInfoList)
{
object observedObject = propertyInfo.GetValue(this, null);
if (observedObject is INotifyPropertyChanged)
{
(observedObject as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(BusinessPropertyChanged);
}
}
}
...
}

Saturday 25 October 2008

Generic Constraints

ConstraintMeaning in Life
where T : structThe type parameter <T> must have System.ValueType in its chain of inheritance.
where T : classThe type parameter <T> must not have System.ValueType in its chain of inheritance (e.g., <T> must be a reference type).
where T : new()The type parameter <T> must have a default constructor. This is very helpful if your generic type must create an instance of the type parameter, as you cannot assume the format of custom constructors. Note that this constraint must be listed last on a multiconstrained type.
where T : NameOfBaseClassThe type parameter <T> must be derived from the class specified by NameOfBaseClass.
where T : NameOfInterfaceThe type parameter <T> must implement the interface specified by NameOfInterface.

The syntax for defining both inheritance and constraints is:

class FSM : AbstractFSM, INotifyPropertyChanged
where TState : struct
where TEvent : struct
{


To define multiple constraints for a single type parameter separate them with commas. It seems like "new()" has to be the last in the list.

private void CollectionConstructorTest()
where TVCollection : VCollection, new()
where TVClass : VClass, new()
{

WPF Cross-Thread Collection Binding

From the rather excellent QuantumBit Designs there are a series of articles about multithreading and collections.

The "grand solution" can be found here: WPF Cross-Thread Collection Binding - Part 4 - The Grand Solution

Features
-Allows WPF to bind to a collection that is modified from any thread
-Allows WPF to bind to properties of items in the collection that are modified from any thread
-No lock required if used from a single worker thread
-Relatively simple (compared to some other attempts)
-Non-blocking

Downsides
-Requires two lists internally
-The ObservableCollection list should not be modified
-Disposable or DependencyObjects should not be used

I've implemented the ObservableList in the test project InABind but we haven't confirmed the overhead involved of using ObservableList in place of ObservableCollection.

Memory Usage

The Sandstorm client app is currently using about 83mb of RAM at runtime. It also consumes up to 25% of CPU time when idle. When the app is minimised the CPU usage drops to 0%. The CPU usage is regardless of whether Sandstorm is being run from within the VS2008 IDE.

I ran a little test app and its RAM footprint topped out at 39mb when run inside the VS2008 IDE. Running as a standalone exe it used a more "modest" 23mb. Interestingly it used no CPU time when idle.

Finding memory leaks in WPF based applications

Avoiding WPF Memory leak with Databinding

A memory leak may occur when you use data binding in Windows Presentation Foundation

Martin and I concluded that we need to implement INotifyPropertyChanged on any class that will be involved in Databinding. The most likely route will be to derive all the relevant classes from a base class that implements INPC.

This tool has a "visual profiler" which shows a graph of CPU usage.

WPF Performance Tool

Tuesday 21 October 2008

INotifyPropertyChanged

We've had a problem with classes that implement this interface failing to serialize. The solution would appear to be this attribute:

[field:NonSerialized]

public event PropertyChangedEventHandler PropertyChanged;
That attribute prevents the delegate field which the compiler emits to implement the PropertyChanged event from being serialized. Since a delegate internally stores hard references to its listeners, you need to prevent that delegate from being serialized. If the delegate were serialized then it would attempt to serialize the objects to which it points.

Expression Blend - with Diagnostics

There’s an interesting point in this post which states you can run Expression with the –diagnostics command line argument and it brings in a Debug menu with some interesting diagnostics/performance options

http://blogs.msdn.com/johngossman/archive/2008/10/16/expression-architecture.aspx

Sunday 19 October 2008

ObservableCollection<T>

Following on from the previous post where I noted that ObservableCollection<T>.CollectionChanged didn't do what I wanted, I've created my own version of ObservableCollection that exposes a new event ItemPropertyChanged. I then hook up to the PropertyChanged event of the business object as it is added to the collection. The new class adds a new property HasChanges which reflects the change status of any property in any business object in the collection.

Caveats:
The business object must implement INotifyPropertyChanged.
There is no "undo" mechanism to set the HasChanges flag back to false

public class MyObservableCollection : ObservableCollection
{
public new void Add(T item)
{
// If the class represented by T implements the INotifyPropertyChanged
// interface hook up the PropertyChanged event handler
if ((item as INotifyPropertyChanged) != null)
{
(item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(OnItemPropertyChanged);
}
base.Add(item);
}

public bool HasChanges { get; set; }
public event PropertyChangedEventHandler ItemPropertyChanged;
public MyObservableCollection()
{
HasChanges = false;
}
protected void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
HasChanges = true;
OnPropertyChanged("HasChanges");
}
protected void OnPropertyChanged(string propertyName)
{
if (ItemPropertyChanged != null)
{
ItemPropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

If an object of this type is bound directly to the DataContext (or ObjectDataProvider) the HasChanges property can be referenced directly in the xaml.

If the collection object is intantiated by a Model class the Model will need to implement INotifyPropertyChanged and expose its own HasChanges property with its value set by wiring up the ItemPropertyChanged event:
public MyObservableCollection Abc { get; set; }

public Model()
{
Abc = new MyObservableCollection();
Abc.ItemPropertyChanged += new PropertyChangedEventHandler(BusinessPropertyChanged);
}
public bool HasChanges
{
get { return Abc.HasChanges; }
}
protected void BusinessPropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged("HasChanges");
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

Friday 17 October 2008

ObservableCollection<T>.CollectionChanged

According to the documentation: "This event occurs when an item is added, removed, changed, moved or the entire list is refreshed."

However it does not occur if a property on an object in the collection changes, even if that object implements the INotifyPropertyChanged.

The new value of the object's property is reflected in the UI automatically (as you would expect of an ObservableCollection).

I wanted to know that something inside the collection had changed so that I could set a HasChanges property on the Model that the UI is bound to via its ObjectDataProvider. The intention was then to have a visual clue on the UI that was bound to the HasChanges property.

This posting doesn't have a solution, its simply a reminder not to try to use this event for this purpose in the future.

Tuesday 14 October 2008

Walking the VisualTree

This isn't all my own code but I thought it might be handy to keep track of some code that walks the VisualTree recursively and also does something with event handlers.

AddHandlers(this);

public void AddHandlers(DependencyObject dependencyObject)
{
int childCount = VisualTreeHelper.GetChildrenCount(dependencyObject);
for (int childIndex = 0; childIndex < childCount; childIndex++)

DependencyObject childObject = VisualTreeHelper.GetChild(dependencyObject, childIndex);

// In this example we're only interested in TextBoxes
if (childObject is TextBox)
{
if ((childObject as TextBox).GetBindingExpression(TextBox.TextProperty).ParentBinding.UpdateSourceTrigger == UpdateSourceTrigger.PropertyChanged)
{
(childObject as TextBox).TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
}
}
AddHandlers(childObject);
}
}

Monday 13 October 2008

Page / Window Constructor

According to Rockford Lhotka:

"Putting code in a Page/Window constructor is bad. Yes, I know it is the “C# way”, but it is bad. The “VB way” of putting code in the Loaded event handler is better.

Why?

Because any exceptions thrown in the constructor prevent the page/window from loading at all, and you have to catch those exceptions in the code that is creating the page/window. In many navigation scenarios you can’t catch them, so the user gets an ugly WPF exception dialog.

However, if you do all your init work in the Loaded event handler, the page/window instance already exists. Navigation has already happened, so the “calling code” is no longer responsible for your page/window going haywire. Instead, you can actually handle the exception and show a nice dialog, explaining to the user what happened, and you can (if desired) navigate somewhere else or whatever."

Monday 6 October 2008

Sorting a collection using Linq and 'SortExpression' string

Bruce suggested that we use LINQ to sort collections. I found the following code on Miron Abrahason's blog but haven't had the chance to try it out yet.

Already happened to you that you had a collection of object from type 'X' with some properties, and you had to sort it one time by property 'ID', and another time by property 'Name' ? You wished that you can sort it by just using a 'Sort Expression' ? If still not, I'm sure this moment will arrive sooner or later. Let me save you some time and an headache.

This is how it can be done:

public static IEnumerable Sort(this IEnumerable source, string sortExpression)
{
string[] sortParts = sortExpression.Split(' ');
var param = Expression.Parameter(typeof(T), string.Empty);
try
{
var property = Expression.Property(param, sortParts[0]);
var sortLambda = Expression.Lambda>(Expression.Convert(property, typeof(object)), param);
if (sortParts.Length > 1 && sortParts[1].Equals("desc", StringComparison.OrdinalIgnoreCase))
{
return source.AsQueryable().OrderByDescending(sortLambda);
}
return source.AsQueryable().OrderBy(sortLambda);
}
catch (ArgumentException)
{
return source;
}
}

Just drop it in a static class, and you will be able to sort any collection that implement the interface IEnumerable.

Lets say you have a class 'User':
public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
}

and a List collection: users. You can sort it however you want:
IEnumerable sortedUsersIEnumerable = users.Sort("ID desc");

Or
List sortedUsersList = users.Sort("Name").ToList();

Sunday 5 October 2008

WPF Keyboard Focus

Mark Smith posted a series of very practical series of three articles about this subject.

Part 1: It's Basically Focus
Part 2: Changing WPF Focus in Code
Part 3: Shifting focus to the first available element in WPF

Exceptions in Converters

Karl Shifflett says:

It is vital that your value converters not throw or be allowed to bubble exceptions because the data binding pipeline does not catch, swallow or handle these exceptions. Instead your users will get those messy exceptions messages because there is no method to catch and handle exceptions in XAML markup. Ensure that if your converter fails that you gracefully handle this conversion or convert back operation.

Validation and Conversion

The default order is for the ValidationRule to be called before the ConvertBack method of the IValueConverter. This means that the ValidationRule may have to do the same conversion as the converter before it can do the validation.

This order can be changed by specifying the ValidationStep.

<TextBox
MinWidth="100"
Style="{StaticResource tbStyle}"
>
<Binding Path="Dob" Converter="{StaticResource dateFormattingConverter}">
<Binding.ValidationRules>
<app:DobValidationRule ValidationStep="ConvertedProposedValue"/>
</Binding.ValidationRules>
</Binding>
</TextBox>

Resource inheritance


If dictionaries being merged have a duplicate key, the last one wins (unlike the case of having duplicate keys in a single dictionary).  Thus inheritance can be handled by the order in which the MergeDictionaries are loaded in the ResourceDictionary section Start by loading the BASE, then the next down etc.. and itll override every time it meets a duplicate.

For reference its on page 250ish in Martin's Unleashed book

Dynamic vs Static Resources :

SR means the resource is applied only once (the 1st time it’s needed).

DR means the resource is reapplied every time it changes.

The main difference between DR and SR is that any subsequent updates to the resource are reflected only to those elements that use DR.

SR and DR have different performance characteristics. DR requires more overhead than SR because of the extra overhead of tracking, while DR can potentially improve load time because SR are always loaded when the Window or Page loads, whereas the DR reference is only loaded when it’s actually used.

DR can also only set dependency properties whereas SR can be used almost anywhere

How are StaticResource and DynamicResource different


This was copied from http://wpfxaml.spaces.live.com/blog/cns!97DD5FD32788695B!142.entry for my own easy reference

Everyone one knows that StaticResource let’s one set a property of an element once.
If the Desktop Color is changed while the element’s application is running, the element keeps its original color:


    <Button>
      <Button.Background>
        <SolidColorBrush Color="{StaticResource {x:Static SystemColors.DesktopColorKey}}" />
      </Button.Background>
      Hello
    </Button>


On the other hand, if the element’s color is set using a DynamicResource, it changes when the Desktop Color changes:

    <Button>
      <Button.Background>
        <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.DesktopColorKey}}" />
      </Button.Background>
      Hello
    </Button>

Why is that? The answer comes from the way these two Resource finders work:

    1.       StaticResource – Finds the resource given in by the ResourceDictionary key, and keeps the resource value;
    2.       DynamicResource – Finds the resource in the ResourceDictionary and keeps the key.

So, it is simple, really.
Since DynamicResource keeps the resource Key instead of the resource value, every event change fired from the resource lets the DynamicResource know that its value has changed.
This is why the DynamicResource reacts to the resource changes, while the StaticResource can’t know the resource has changed, since it only keeps the resource’s final value.

C# String Formatting

C# String Formatting

UPDATE: I show alternate ways to use string formats in WPF in this post:WPF String Formatting

This entry has been copied from SteveX (http://blog.stevex.net/index.php/string-formatting-in-csharp/) for my own easy reference.

The text inside the curly braces is {index[,alignment][:formatString]}. If alignment is positive, the text is right-aligned in a field the given number of spaces; if it’s negative, it’s left-aligned.

Strings

There really isn’t any formatting within a string, beyond it’s alignment. Alignment works for any argument being printed in a String.Format call.
Sample Generates
String.Format(”->{1,10}<-”, “Hello”); -> Hello<-
String.Format(”->{1,-10}<-”, “Hello”); ->Hello <-

Numbers

Basic number formatting specifiers:

Specifier Type Format Output (Passed Double 1.42) Output (Passed Int -12400)
c Currency {0:c} $1.42 -$12,400
d Decimal (Whole number) {0:d} System.FormatException -12400
e Scientific {0:e} 1.420000e+000 -1.240000e+004
f Fixed point {0:f} 1.42 -12400.00
g General {0:g} 1.42 -12400
n Number with commas for thousands {0:n} 1.42 -12,400
r Round trippable {0:r} 1.42 System.FormatException
x Hexadecimal {0:x4} System.FormatException cf90

Custom number formatting:

Specifier Type Example Output (Passed Double 1500.42) Note
0 Zero placeholder {0:00.0000} 1500.4200 Pads with zeroes.
# Digit placeholder {0:(#).##} (1500).42
. Decimal point {0:0.0} 1500.4
, Thousand separator {0:0,0} 1,500 Must be between two zeroes.
,. Number scaling {0:0,.} 2 Comma adjacent to Period scales by 1000.
% Percent {0:0%} 150042% Multiplies by 100, adds % sign.
e Exponent placeholder {0:00e+0} 15e+2 Many exponent formats available.

;
Group separator
see below

The group separator is especially useful for formatting currency values which require that negative values be enclosed in parentheses. This currency formatting example at the bottom of this document makes it obvious:

Dates

Note that date formatting is especially dependant on the system’s regional settings; the example strings here are from my local locale.

Specifier Type Example (Passed System.DateTime.Now)
d Short date 10/12/2002
D Long date December 10, 2002
t Short time 10:11 PM
T Long time 10:11:29 PM
f Full date & time December 10, 2002 10:11 PM
F Full date & time (long) December 10, 2002 10:11:29 PM
g Default date & time 10/12/2002 10:11 PM
G Default date & time (long) 10/12/2002 10:11:29 PM
M Month day pattern December 10
r RFC1123 date string Tue, 10 Dec 2002 22:11:29 GMT
s Sortable date string 2002-12-10T22:11:29
u Universal sortable, local time 2002-12-10 22:13:50Z
U Universal sortable, GMT December 11, 2002 3:13:50 AM
Y Year month pattern December, 2002

The ‘U’ specifier seems broken; that string certainly isn’t sortable.

Custom date formatting:

Specifier Type Example Example Output
dd Day {0:dd} 10
ddd Day name {0:ddd} Tue
dddd Full day name {0:dddd} Tuesday
f, ff, … Second fractions {0:fff} 932
gg, … Era {0:gg} A.D.
hh 2 digit hour {0:hh} 10
HH 2 digit hour, 24hr format {0:HH} 22
mm Minute 00-59 {0:mm} 38
MM Month 01-12 {0:MM} 12
MMM Month abbreviation {0:MMM} Dec
MMMM Full month name {0:MMMM} December
ss Seconds 00-59 {0:ss} 46
tt AM or PM {0:tt} PM
yy Year, 2 digits {0:yy} 02
yyyy Year {0:yyyy} 2002
zz Timezone offset, 2 digits {0:zz} -05
zzz Full timezone offset {0:zzz} -05:00
: Separator {0:hh:mm:ss} 10:43:20
/ Separator {0:dd/MM/yyyy} 10/12/2002

Enumerations

Specifier Type
g Default (Flag names if available, otherwise decimal)
f Flags always
d Integer always
x Eight digit hex.

Some Useful Examples

String.Format(”{0:$#,##0.00;($#,##0.00);Zero}”, value);

This will output “$1,240.00? if passed 1243.50. It will output the same format but in parentheses if the number is negative, and will output the string “Zero” if the number is zero.

String.Format(”{0:(###) ###-####}”, 8005551212);

This will output “(800) 555-1212?.

WPF ComboBox Data Binding

Binding a enum property (PaymentFrequency) to a WPF ComboBox.
This property provides the ItemsSource for the combobox by building a dictionary of enum (key) and enum.ToString (value).
   public enum PaymentFrequency
   {
      DayOfPlay,
      Monthly,
      None,
      Quarterly,
      Weekly,
   }
Expose this as a Property and Dictionary for Binding purposes:
      public PaymentFrequency Frequency { get; set; }

      public IDictionary<PaymentFrequency, string> FrequencyList
      {
         get
         {
            IDictionary<PaymentFrequency, string> frequencyList = new Dictionary<PaymentFrequency, string>();
            foreach (PaymentFrequency pf in Enum.GetValues(typeof(PaymentFrequency)))
            {
               frequencyList.Add(pf, pf.ToString());
            }
            return frequencyList;
         }
      }
The corresponding xaml (not forgetting the UpdateSourceTrigger=PropertyChanged if the ComboBox is inside a DataGrid as discussed here):
      <ComboBox ItemsSource="{Binding Path=FrequencyList, Mode=OneTime}"
                SelectedValuePath="Key"
                DisplayMemberPath="Value"
                SelectedValue="{Binding Path=Frequency, UpdateSourceTrigger=PropertyChanged}">
      </ComboBox>
For Internationalisation purposes it would be better to use Resource Strings to provide the descriptions for the combobox. I used a prefix of "PF_" on all the strings to ensure they are unique:

PF_DayOfPlay Day of Play 
PF_Monthly Monthly 
PF_None  None 
PF_Quarterly Quarterly 
PF_Weekly Weekly
Then modify the FrequencyList getter:
      public PaymentFrequency Frequency { get; set; }

      public IDictionary<PaymentFrequency, string> FrequencyList
      {
         get
         {
            IDictionary<PaymentFrequency, string> frequencyList = new Dictionary<PaymentFrequency, string>();
            foreach (PaymentFrequency pf in Enum.GetValues(typeof(PaymentFrequency)))
            {
               frequencyList.Add(pf, ResourceStrings.ResourceManager.GetString("PF_" + pf.ToString()));
            }
            return frequencyList;
         }
      }
A final tweak is to sort the descriptions displayed in the combobox into alphabetic order based on the translated strings.
      public PaymentFrequency Frequency { get; set; }

      public IDictionary<PaymentFrequency, string> FrequencyList
      {
         get
         {
            IDictionary<PaymentFrequency, string> frequencyList = new Dictionary<PaymentFrequency, string>();
            foreach (PaymentFrequency pf in Enum.GetValues(typeof(PaymentFrequency)))
            {
               frequencyList.Add(pf, ResourceStrings.ResourceManager.GetString("PF_" + pf.ToString()));
            }
            return frequencyList.OrderBy(f => f.Value).ToDictionary(f => f.Key, f => f.Value);
         }
      }
The ComboboxDataBinding example project includes this code and can be downloaded from GoogleCode.

CompareTo method

CompareTo() is very easy to understand but I just seem to have a blind spot about it.

int result = instance.CompareTo(obj);

ResultMeaning
Less than zeroinstance is less than obj
Zeroinstance is equal to obj
Greater than zeroinstance is greater than obj

For thisUse this
if (instance < obj)if (instance.CompareTo(obj) < 0)
if (instance <= obj)if (instance.CompareTo(obj) <= 0)
if (instance == obj)if (instance.CompareTo(obj) == 0)
if (instance > obj)if (instance.CompareTo(obj) > 0)
if (instance >= obj)if (instance.CompareTo(obj) >= 0)

Sorting Generic Collections

You can simplify the sorting by using the anonymous delegate as shown below and you don't need to implement IComparable interface:

(Note: For a simpler technique using LINQ see: Sorting Generic Collections - Redux)
List persons = new List();
persons.Add( new Person("Tom",30) );
persons.Add(new Person("Harry", 55));

// sort in ascending order
persons.Sort( delegate(Person person0, Person person1)
{
return
person0.FirstName.CompareTo(person1.FirstName);
} );


// sort in descending order
persons.Sort( delegate(Person person0, Person person1)
{
return
person1.FirstName.CompareTo(person0.FirstName);
} );