Winforms technology enjoyed its dominance until Windows Presentation Foundation (WPF) made an entry and completely over took this legacy technology. It is now the preferred choice for developing the enterprise scale apps for desktops. It was an easy decision for companies to migrate their existing winforms code by doing simply copy and paste option. As most of the code behind written in winforms would just run in WPF, obviously the UI needs to be redeveloped. But that would defy the purpose of using the rich technology of WPF which supports data binding and eye catching glossy UI. Moreover if you are developing in WPF and are not adapting to the MVVM pattern then you are committing a serious crime. Eventually your app will grow and it would get nightmares for maintaining it.
In this blog post I talk about how I converted existing Winform Camera Control and encapsulated its entire functionality in the WPF User control so it can be reused across the project.
Just let me introduce to you about the functionality of this project. There should be live streaming from the webcam in your application and the user should be able to take the snapshot of the on going frame. The image should be saved in users Pictures library folder. Quite a simple requirement and there are tons of samples out there which can help us to nail this problem, but all those solutions violates the MVVM pattern. My solution follows the MVVM pattern religiously and still achieves the desired functionality.
I’m using Aforge framework to capture the camera output stream. This is quite extensive framework which does more than image processing. You can get more info by reading its documentation.
Create a new WPF application. Download MVVM Light toolkit libraries from the Nuget. Now add the Aforge libraries. You would require the following
Please note that all these above Aforge libraries can also be obtained from the Nuget.
Now comes the two important assemblies that you would require to reference in your project and they are
These two assemblies allow us to integrate winform controls in xaml. You can virtually use any winform control via these assemblies. Just nest it under the WindowsFormHost and you are done.
I LOVE XAML
XAML and MVVM are made for each other. One of the cool features of any XAML based technologies is rich data binding. This feature allows us to bind any visual element. The only prerequisite for data binding is that the property to which you are binding should be a dependency property.
You can also create your own dependency properties of the user control and program it to the way you want. Create a new folder in your project and name it to ‘Controls’. Add a new UserControl to this folder and name it AForgeWebCam.xaml. Copy the below code in it.
Switch to the code behind of this user control , where we would create all the required dependency properties. We would require following dependency properties.
1)AvailableCameraSources : This will list down all the attached camera with the device name and unique id. This property will be of type IList<DeviceInfo>. The DeviceInfo is a simple class with two properties.
Have a look at line number 6 in the above code , the last argument of dependency property is PropertyMetaData , whose one constructor accepts one parameter Object type. Using this parameter the developer can set the default value of the dependency property. So here I initialize this property by calling private static method GetCameraSources. This constructor also accepts the other arguments which I will explain later.
2)CameraId : This is of string type . The value is basically the unique id of the camera by which the operating system identifies it. This is used by AForge VideoSourcePlayer control to render the video streaming.
Notice the two call-back methods OnCameraValueChanged and OnCameraCoherceValueChanged.The first call back methods handles the starting and stopping of the camera.The coerce call-back method allows us to adjust the value if of the property if it is not within the required range and throwing exception.
3)TakePictureCommand : This property is of ICommand type. And its default value is set to TakeInteralPictureCommand private property. The action of this command encapsulates all the logic of taking the picture. A thing to note over here is that Aforge framework does not provide this functionality out of the box. I have written the custom code to achieve this. I capture the position of the control and using the apis available in System.Drawing namespace I create new image and save it to the pictures folder. See the code below
The whole idea of wrapping up the entire camera functionality in the UserControl was the code reuse. This control can be now dropped into any xaml window, page or even other user control.
Using the element data binding capabilities I have binded the Combo box. So as a developer who is consuming your control does not have to bother about getting the camera sources because your control already exposes that as a dependency property.
The api of the usercontrol is quite simple , to connect to the camera set the CamerId property to the valid connection string, to disconnect it make it null or set the property to empty string.
Using WinFormHost control in WPF lot of existing controls can be reused. The only challenge lies how you ensure that your MVVM design in not getting compromised with this implementation. If planned smartly then this can be taken care off. I hope you must have enjoyed the reading this article. Please leave your valuable feedback in the comments. Download the sample code from here.