// Single click
this.TradesGrid.SelectionChanged += TradesGridSelectionChanged;
// Double click
this.TradesGrid.AddHandler(GridViewCellBase.CellDoubleClickEvent,
new EventHandler<RadRoutedEventArgs>(OnCellDoubleClick), true);
......
void TradesGridSelectionChanged(object sender, SelectionChangeEventArgs e)
{
if (e.AddedItems.Count == 0) return;
var trade = e.AddedItems[0] as Trade;
if (trade == null) return;
var vm = DataContext as ViewModel;
if (vm == null) return;
vm.OpenTradeForDocumenting(trade);
}
private void OnCellDoubleClick(object sender, RadRoutedEventArgs e)
{
var cell = e.Source as GridViewCell;
if (cell == null) return;
var row = cell.ParentRow as GridViewRow;
if (row == null) return;
var trade = row.DataContext as Trade;
if (trade == null) return;
var vm = DataContext as ViewModel;
if (vm == null) return;
vm.OpenTradeForDocumenting(trade);
}
Wednesday, 28 November 2012
Telerik Silverlight GridView click events
Friday, 20 April 2012
Weak Event Handlers
Why would you need to use a Weak Event handler? Take a look at this example of normal events and handlers:
Notice how the Console window is empty. The Subscriber finalizer ~Subscriber() which writes to the console window has not been called meaning our subscriber is still in memory. This is due to the Publisher event holding a strong reference to the Subscribers event handler (see the watch window).
Why not just implement IDispose and unsubscribe from the event?
This is the ideal scenario but you are relying upon our Publisher being considerate enough to call dispose on the Subscriber. This means we can remove the event handler, notice how the publishers event is now null, which means the GarbageCollector can collect our subscriber.
But what happens if the Publisher forgets to “dispose” of the subscriber? We still have a memory leak.
Weak Reference Events to the rescue!
We can see here in the watch window that the publishers event still has a reference to the subscribers event handler. But the subscriber has been disposed…. cool!
This is all possible that to the use of a WeakReference.
Special thanks to Distin Campbell, Joe Duffy, Xavier Musy and Gregor R. Peisker.
using System;
using System.Reflection;
public delegate void UnregisterCallback<E>(EventHandler<E> eventHandler)
where E : EventArgs;
public interface IWeakEventHandler<E>
where E : EventArgs
{
EventHandler<E> Handler { get; }
}
public class WeakEventHandler<T, E> : IWeakEventHandler<E>
where T : class
where E : EventArgs
{
private delegate void OpenEventHandler(T @this, object sender, E e);
private WeakReference _targetRef;
private OpenEventHandler _openHandler;
private EventHandler<E> _handler;
private UnregisterCallback<E> _unregister;
public WeakEventHandler(EventHandler<E> eventHandler, UnregisterCallback<E> unregister)
{
_targetRef = new WeakReference(eventHandler.Target);
_openHandler = (OpenEventHandler) Delegate.CreateDelegate(
typeof(OpenEventHandler), null, eventHandler.Method);
_handler = Invoke;
_unregister = unregister;
}
public void Invoke(object sender, E e)
{
T target = (T) _targetRef.Target;
if (target != null)
_openHandler.Invoke(target, sender, e);
else if (_unregister != null)
{
_unregister(_handler);
_unregister = null;
}
}
public EventHandler<E> Handler
{
get { return _handler; }
}
public static implicit operator EventHandler<E>(WeakEventHandler<T, E> weakEventHandler)
{
return weakEventHandler._handler;
}
}
public static class EventHandlerUtils
{
public static EventHandler<E> MakeWeak<E>(this EventHandler<E> eventHandler, UnregisterCallback<E> unregister)
where E : EventArgs
{
if (eventHandler == null)
throw new ArgumentNullException("eventHandler");
if (eventHandler.Method.IsStatic || eventHandler.Target == null)
throw new ArgumentException("Only instance methods are supported.", "eventHandler");
Type weakEventHandlerType = typeof(WeakEventHandler<,>).MakeGenericType(
eventHandler.Method.DeclaringType, typeof(E));
ConstructorInfo weakEventHandlerConstructor = weakEventHandlerType.GetConstructor(
new Type[] { typeof(EventHandler<E>), typeof(UnregisterCallback<E>) });
IWeakEventHandler<E> weakEventHandler = (IWeakEventHandler<E>)weakEventHandlerConstructor.Invoke(
new object[] { eventHandler, unregister });
return weakEventHandler.Handler;
}
}
Performance
Who wants to see a shoot out between strong event handlers and our weak event handler solution?Ok, so first up here’s the code for our benchmarks:
using System;
using System.Diagnostics;
class Performance
{
const int iterations = 1000000;
public static void Main()
{
Console.WriteLine("Running tests with {0} iterations", iterations);
RunTest("StrongEvent", new StrongEvent.Publisher());
RunTest("StrongEventDisposable", new StrongEventDisposable.Publisher());
RunTest("WeakEvent", new WeakEvent.Publisher());
}
public static void RunTest(string name, IPublisher publisher)
{
GC.Collect();
GC.WaitForPendingFinalizers();
var stopwatch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
publisher.CreateSubscriber();
publisher.DestroySubscriber();
}
stopwatch.Stop();
Console.WriteLine("{0} took {1} ms", name, stopwatch.ElapsedMilliseconds);
}
}
Results
Ouch! You win some, you lose some
The results are very interesting, in conclusion it really does pay to be a good .NET citizen, removing event handlers and disposing of an IDisposable wins here.
Microsoft have come up with the Weak Event Pattern for WPF: http://msdn.microsoft.com/en-us/library/aa970850.aspx
I wonder if Microsoft will come up with a better and more generic solution for weak event handlers in .NET 4.5.
Source
http://stevenhollidge.com/blog-source-code/WeakEventReference.zip
Note: The finalizers have been commented out in the code so as not to affect the performance tests.
Thursday, 29 March 2012
WPF Interop: COM, ActiveX OCX and PDF fun
Here is an application that displays a PDF file inside a WPF window.
To do this, the easiest way is to interop with the Adobe Reader COM ActiveX (OCX) control.
So how does WPF deal with COM and ActiveX (OCX controls), given the disparity between how classic Win32 and WPF handles HWNDs.
| Classic Win32: | One HWND per control |
| WPF: | One HWND per window/dialog |
The solution is to create:
- a WPF window containing
- a WindowsFormsHost control containing
- a WinForms User Control containing
- the ActiveX control
For our example we’ll be using the Adobe Acrobat Reader and you will need this installed if you wish to run the code and application.
Please note:
You cannot use this COM component outside of the main UI thread as the OCX is not thread-safe.
Here are the steps I took:
Add WinForms User Control
Add COM Reference to the project
“Add Tab” to the Toolbox called Adobe, “Choose Items…” and add the Adobe PDF Reader
You can now drag and drop the Adobe PDF Reader control from the Toolbox onto the WinForms User Control.
By dragging the control onto the surface it ensures the OCX is correctly registered by the form.
What C# code does that actually produce?
Add your code behind to the WinForms User Control
Finally, add a WindowsFormsHost control to your WPF window and add the WinForms UserControl as a child
To print just right click on the document and select Print.
Here is the same solution with a notify event raised by the WinForm User Control, to enable communication with the Wpf window:
Source code: http://stevenhollidge.com/blog-source-code/PdfViewAndPrint.zip
Source code: http://stevenhollidge.com/blog-source-code/PdfViewAndPrint_with_event.zip
Friday, 17 February 2012
Rx Event Example
When subscribing to events Reactive Extensions (Rx) is a powerful way to filter, throttle and compose your .Net code.
With this example I have a WPF application that listens to a FxRate pricing service, that’s pumping out 100 new prices a second via an event.
I’m going to make available the code to show how to hook up the front end Metro style application using MVVM with:
- old skool event handlers
- and then using Reactive Extensions (Rx)
Finally we update the Rx example to filter on just one of the exchange rates and also throttle back the rate of FxRates being received to one per second.
The event signature
Old skool event handlers
Using MVVM, here we have my view model code stripped back just to show we have:
- A pricing service
- A subscribed command (data bound to the subscribed button on the UI) which toggles the subscribed property
- A delegate (PriceUpdate) that handles the event when the subscribed button is clicked. Click the button a second time to unsubscribe and remove the delegate from handling the event
Lines 25 and 30 show the adding and removal of the event handler, dependent on whether the user has clicked the subscribe button.
Rx Subscriptions
To do the same thing with Rx takes two lines of code (lines 18/19 and 21)
Filtering with Rx
Simply update our subscription to include a where filter that accepts the event coming in (e) and sets the predicate to Ccy (Currency) for the exchange to Euro to GBP.
Throttling with Rx
NOTE: The code below was a workaround, please use Sample as shown here.
So we have filtered the events to only give us the Euro to GBP prices. Now let's enhance the solution just to give us the latest Euro to GBP price every two seconds.
Source code
Event handlers: http://stevenhollidge.com/blog-source-code/standard-event-handler-wpf-metro-mvvm-stockmarket-pricing-app.zip
Reactive Extensions: http://stevenhollidge.com/blog-source-code/Rx-wpf-metro-mvvm-stockmarket-pricing-app.zip
Tuesday, 14 February 2012
Reactive Extensions (Rx)
Overview
MSDN Definition
“Rx is a library to compose asynchronous and event-based programs using observable collections and LINQ-style query operators.”
Rx provides extension methods on top of Linq to enable developers to implement the observer pattern on query results (IEnumerables e.g. a collection or sequence).
The benefits of Rx are in it’s enabling of concurrency and it’s composability. It allows for easy concurrent processing over a collection along with simple declarative call backs on completion and exceptions. This programming model allows for simple orchestration of async operations.
To get familiar with Rx, in the examples below we’ll look at simple enumerations of data to get a feel for the programming style. We can then take a look at Rx for events, with events after all just being a sequence of data (found in the EventArgs).
How To Get Reactive Extensions
Use Nuget, search for Rx and bring in the Reactive.Main library (System.Reactive namespace).
Simple example
1.Convert the linq query into an observable (using the Rx extension method).
2. Write a delegate which will execute for:
- Each item in the enumeration (OnNext method in the examples below)
- When an error occurs (OnError method in the examples below)
- When the enumeration completes (OnCompleted method in the examples below)
3. Subscribe to the query results. This is whether you hook up each of your delegates and start the enumeration.
“Finally” delegate
There is another delegate we can set, that runs after the processing has completed, regardless of whether the enumeration successfully got the end of the sequence or not e.g. An error occurred half way through processing so the completed delegate doesn’t run. The Finally delegate will always run which might be useful for clean up.
How to Configure Threading
Notice how all the "getting" and "processing" are sequential and in keeping with the enumeration (within each group) even though the processing might be occurring on different threads.
Early Cancellation of Processing
You can cancel the processing of a collection, here is an example:
“Using” A Disposable Object
This example code disposes of an object after the completed delegate has run.
A real world example may look like this:
Demo Source Code
You can download the demo here: http://stevenhollidge.com/blog-source-code/RxExtensionsDemo.zip
Friday, 26 August 2011
Threadsafe Events in .Net
Usually the event pattern used by C# devs would be something long these lines:
When actually this provides for a cleaner threadsafe implementation:
Thanks to Rob Eisenberg for the suggestion!
Remember the event keyword is just a modifier for a delegate declaration that allows it to be included in an interface, constraints it invocation from within the class that declares it, provides it with a pair of customisable accessors (add and remove) and forces the signature of the delegate (Object sender, EventArgs e).