Archive

Archive for the ‘WPF’ Category

Accessing WPF controls on a non UI Thread

March 14, 2010 Leave a comment

I am sure most of you would have run into this issue before. When you try to access a WPF control on a different thread other than your regular UI thread you get a runtime exception “The calling thread cannot access this object because a different thread owns it.”. To understand why this happens, it is important to know that WPF applications run on two different threads – one for rendering the controls and the other to manage the user interface. The rendering thread runs in the background and the thread which is visible for us to work on is the UI thread. And hence most of the objects are tied to the UI thread and this is known as thread affinity. Thread affinity is handled by the Dispatcher. Each user interface related work item is channeled through the Dispatcher class, that means every work item is queued by the UI thread in an object called Dispatcher. Dispatcher runs the work items on priority basis. Supporting work item prioritization allow WPF to work on a an item for more time and hence more time is consumed on the UI thread. UI thread will have at least one Dispatcher, and each Dispatcher can execute work items in exactly one thread. So it is important to release the work item from the thread as fast as possible so as to increase the UI responsiveness.  To keep the work item small,  I spawned newer threads and executed the discrete blocks of code on these threads. This is exactly where I ran into the exception stated above (when I tried to access the  WPF control).

So here is how I got the exception:

private void myButton_Click(object sender, RoutedEventArgs e)
{
    Thread t = new Thread(new ThreadStart(
        delegate
        {
            //accessing the TextBlock.Text on a different thread – **incorrect**
            myText.Text = "HI";
        }
        ));
    t.Start();
}

 

So how to get rid of this?

Now we know why a background running thread cannot access the UI thread. To get rid of this problem it is pretty simple – “Just ask the UI thread to do it for you”. Yes the background thread can request the UI thread to update the control properties on behalf of it. This is achieved by calling the Invoke or the BeginInvoke method of the DispatcherObject class. This will register the work items to the Dispatcher. Invoke is a synchronous call – that is, it doesn’t return until the UI thread actually finishes executing the delegate. BeginInvoke is asynchronous and returns immediately. So as stated above Dispatcher orders work items by priority and hence you can pass the priority using DispatcherPriority enumerator while registering the work item to Dispatcher. 
So here is the code below which solved my problem:

private void myButton_Click(object sender, RoutedEventArgs e)
{
    Thread t = new Thread(new ThreadStart(
        delegate
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, new Action<TextBlock>(SetValue), myText);
        }
        ));
    t.Start();
}

private static void SetValue(TextBlock txt)
{
    txt.Text = "HI";
}

In the Dispatcher.Invoke() method used above takes three parameters – DispatcherPriority Enum, Delegate to execute the code and the parameter object. I used the Action<T> generic type to pass the control to the method to set its property.

It is suggested to use the setting of the control properties in the UI thread itself, and only move those code like say calculations to another thread. This will provide a better code maintenance.

However in the above example we do not improve the UI responsiveness, as the Invoke() method is called synchronously. Instead use BeginInvoke() method. My intention was to give an insight of the exception – why, and how to deal with it. If you need details on writing better responsive applications refer Shawn Wildermuth’s article

Wow another weekend in research -Cheers!

Animated Gif in WPF using Windows Forms Control

January 11, 2010 3 comments

Loading an animated gif into WPF has been a challenge since the version 1 release. WPF does not support loading an animated gifs directly into an declarative <Image> or by code, and hence developers have come out with various workarounds. Some use a raw technique – writing few lines of code which extracts the frames of the GIF and animate them.  One other way to do is using the <MediaElement> FrameworkElement which is in the namespace System.Windows.Controls. <MediaElement> wraps the MediaPlayer class for declarative use and hence it supports both audio and video files. Using MediaElement you can load the animated gif the following way:

<MediaElement Source="file://D:\anim.gif"/>

Remember it is important to use “file://” and an absolute path for loading the gif. So you cannot embed the image to a resource file and now you know one of the limitations of it. Every approach does have advantages and limitations of its own, its important to use the right approach based on the project needs.

Another possible way is by making the working Jack do the trick – Yeah I meant lets go back to Win Forms picture box to do the magic. We know PictureBox seamlessly loaded the animated gifs in Win Form days. Wait a minute did I say lets change the project from WPF to Win Forms? No I didn’t. What I said is lets integrate the PictureBox alone to the WPF project. To use the right word, I should say that we need to host the Windows Forms Control in WPF. To host a Windows Forms Control you need to make use of the class WindowsFormsHost which appears in the System.Windows.Forms.Integration namespace in assembly WindowsFormsIntegration.dll.

Lets get to the code. The first step to do is add a reference to System.Windows.Forms.dll and WindowsFormsIntegration.dll to your WPF based project.

References

Add the following namespaces to your XAML Code.

<Window x:Class="WpfApplication2.Window1"
    xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
    xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"

Now you can host the PictureBox inside the WindowsFormsHost and set its Name.

    <Grid>
        <wfi:WindowsFormsHost>
            <winForms:PictureBox x:Name="pictureBoxLoading">
            </winForms:PictureBox>
        </wfi:WindowsFormsHost>
    </Grid>

In your code behind(Window1.xaml.cs), add this code to the Window_Loaded Event:

private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.pictureBoxLoading.Image = System.Drawing.Image.FromFile("anim.gif"); ;
        }

Key points before execution:

  1. Make sure you provide the right path to load the image
  2. You can also load it from a resource file.

Since Windows Forms has several interesting built in controls that WPF lacks, using this technique you can make your favorite Windows Forms control work in WPF.

Cheers!

Understanding Dependency Property

July 23, 2009 Leave a comment

Everyone who get introduced to Windows Presentation Foundation(WPF) are familiar with this term. But lot many get confused on it or never get what it is. I will try and make this post very simple so that it is easier to understand. My intentions are not to provide the complete technical stuff behind the Dependency property, but to keep things simple to understand and to get started. You should probably work on this lot many times to understand it better.

If you are not new to .net or any other OOP language, you are not new to Property. Dependency property was introduced in .net 3.0 and it is all together new implementation of normal properties. Dependency property differ in terms of its storage mechanism, it uses Sparse Storage and its implementation saves per-instance memory compared to a typical .NET property. However benefits of dependency property is more than just storage. One of the significances of Dependency property is its support for notification change – that means any change in the value of the property is notified down the element tree in WPF. This point particularly becomes very important to understand this.

Before I completely get on with Dependency property, let me give a gist of what attached property is. Let me explain this in a way a lay man understands: Consider a “<Canvas></Canvas>” element in your XAML. Now if you want to add a child element “<TextBlock>” to it, how do you place them in the canvas? – Here it is:

<Canvas>
       <TextBlock Canvas.Top=”100″ Canvas.Left=”100″ Text=”Hello World”/>
</Canvas>

OR an example with a Grid

<Grid>
   <Grid.ColumnDefinitions>
      <ColumnDefinition/>
      <ColumnDefinition/>
   </Grid.ColumnDefinitions>
   <Grid.RowDefinitions>
      
<RowDefinition/>
      
<RowDefinition/>
   </Grid.RowDefinitions>
  
<TextBlock Grid.Column=”0″ Grid.Row=”0″ Text=”Hello World  1″/>
  
<TextBlock Grid.Column=”1″ Grid.Row=”0″ Text=”Hello World 2″/>
  
<TextBlock Grid.Column=”0″ Grid.Row=”1″ Text=”Hello World 3″/>
  
<TextBlock Grid.Column=”1″ Grid.Row=”1″ Text=”Hello World 4″/> 
 
</Grid>

So what we do is we set the Canvas’s Top and Left property in the TextBlock child element or even the Grid’s Column and Row property in the child elements. This is achieved using attached property.

So here is the MSDN explanation: “An attached property is intended to be used as a type of global property that is settable on any object. One purpose of an attached property is to allow different child elements to specify unique values for a property that is actually defined in a parent element.”

In the above example, we see the property element of a parent is changed by the child, and the same gets reflected throughout the child elements. I have explained this so that you don’t confuse attached property with dependency property.

Let us extend couple of lines of code more and now understand dependency property.

And here it is:

<Canvas>
<Slider Canvas.Top=”10″ Canvas.Left=”10″ Name=”MySlider” Minimum=”10″ Maximum=”1000″ Ticks=”100″ Width=”300″/>
 <Ellipse Canvas.Top=”130″ Canvas.Left=”150″ Width=”{Binding ElementName=MySlider, Path=Value}” Height=”{Binding ElementName=MySlider, Path=Value}” Fill=”Red”/>
 </Canvas>

The output of the above example is: When the slider is moved, automatically the ellipse gets larger or smaller based on the value of the slider. So what we understand from this is without writing event handlers or any code behind to handle the slider movement and the ellipse height and width setters – we achieve this. This is because the property “Value” of the slider is a dependency property and it notifies the change to all the elements in the XAML, and since the Ellipse’s width and height are bound to the “Slider.Value” it automatically reflects the change.

This was just an introduction, there are couple of more things I want to cover like – creating your own dependency properties for the custom controls etc, which will be updated in the next post.

Cheers!

Follow

Get every new post delivered to your Inbox.