Replacing a delegate with an inline lambda expression: Improvements on an MS Exams Custom WPF Control example

I was dusting off my WPF skills when I took a look at the Custom WPF Control example in this book: MCTS Self-Paced Training Kit (Exam 70-511): Windows Application Development with Microsoft .NET Framework 4

The example, in Chapter 5 Lesson 3, is a simple step-by-step exercise to create a basic Digital Clock WPF Control. While trying it out, I made two modifications to the code that I think improves the style.

Here is the code as given by the book:

public class DigitalClockControl : Control
{
	public static readonly DependencyProperty TimeProperty;
	System.Timers.Timer myTimer = new System.Timers.Timer();
	delegate void SetterDelegate();
	
	static DigitalClockControl()
	{
		DefaultStyleKeyProperty.OverrideMetadata(typeof(DigitalClockControl),
			new FrameworkPropertyMetadata(typeof(DigitalClockControl)));
	
		FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
	
		TimeProperty = DependencyProperty.Register("Time",
			typeof(string),
			typeof(DigitalClockControl), metadata);
	}
	
	public DigitalClockControl()
	{
		myTimer.Elapsed += new System.Timers.ElapsedEventHandler(MyTimeElapsedHandler);
		myTimer.Interval = 1000;
		myTimer.Start();
	
		this.DataContext = this;
	}
	   
	void TimeSetter()
	{
		SetValue(TimeProperty, DateTime.Now.ToLongTimeString());
	} 
		
	void MyTimeElapsedHandler(object sender, System.Timers.ElapsedEventArgs e)
	{
		Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
			new SetterDelegate(TimeSetter));
	}
}

Switching from a Setter to a Property

I’m not fond of the TimeSetter() method in line 28. I much prefer Properties to Getters and Setters – in this case you need only declare the Setter:

public string Time { set { SetValue(TimeProperty, value); } }

Changing the Invoke call to use the Property

Since we have now removed the TimeSetter() method, we must change the Dispatacher.Invoke() call in line 35 to assign the desired value directly to the Time property. The neat thing here is that we don’t need the delegate declaration in line 5 anymore:

delegate void SetterDelegate();

We now remove the delegate declaration and put the functionality of the old TimeSetter() method in an inline lambda expression right in the Invoke() call. The Invoke() method still wants a delegate parameter though, so we have to cast the lambda expression to an Action instance:

Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
	(Action)(() => this.Time = DateTime.Now.ToLongTimeString()));

Final Code

Below is the resulting code, without the delegate and using a property instead of a setter method. The results are exactly the same, the only difference is the way it is implemented. And even if the implementation style does not matter to you, it’s still cool to know you could change it if you wanted to. (Oh and lambda’s are way cooler than delegate declarations!)

public class DigitalClockControl : Control
{
	public static readonly DependencyProperty TimeProperty;
	System.Timers.Timer myTimer = new System.Timers.Timer();
	
	static DigitalClockControl()
	{
		DefaultStyleKeyProperty.OverrideMetadata(typeof(DigitalClockControl),
			new FrameworkPropertyMetadata(typeof(DigitalClockControl)));
	
		FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
	
		TimeProperty = DependencyProperty.Register("Time",
			typeof(string),
			typeof(DigitalClockControl), metadata);
	}
	
	public DigitalClockControl()
	{
		myTimer.Elapsed += new System.Timers.ElapsedEventHandler(MyTimeElapsedHandler);
		myTimer.Interval = 1000;
		myTimer.Start();
	
		this.DataContext = this;
	}
	
	public string Time { set { SetValue(TimeProperty, value); } } 
	
	void MyTimeElapsedHandler(object sender, System.Timers.ElapsedEventArgs e)
	{
		Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
			(Action)(() => this.Time = DateTime.Now.ToLongTimeString()));
	}
}
Advertisements
This entry was posted in Software Development and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s