WPF: Making good progress

Recently I came across a situation where I had a list box of items which I wanted to process on separate threads but report progress to the user. I had never had to do something like this in Win32 let alone WPF so I decided to knock up a little prototype which is the basis for this blog entry.

Download the source code: WPF_Progress.zip

The prototype application basically contains a list of video clips which need to be converted. User selects a clip and presses the Convert button which kicks of a new thread to perform the conversion and shows progress through a ProgressBar which is part of the DataTemplate.

SampleAppRunning

First off I defined some simple XAML for the ListBox items:

<Window.Resources> <DataTemplate DataType="{x:Type local:VideoClip}"> <StackPanel x:Name="stack" Background="Gainsboro" Width="200"> <Button x:Name="save" Width="60" Height="20" Click="convert_Click">Convert</Button> <Label Content="{Binding Name}"/> <ProgressBar x:Name="progress" Width="100" Height="15" Maximum="100" Value="{Binding SaveProgress}"/> <Label Content="{Binding Status}"/> </StackPanel> </DataTemplate> </Window.Resources>

Then I wired up the convert_Click event to start a BackgroundWorker thread which runs some code to mimic the conversion. This simply loops for a period of time reporting progress each second or so. The main window hooks into an event on the converter to pick up the progress which can then be set on the ProgressBar.Value.

There were two issues which I came across during this prototype:

1. Accessing the ProgressBar inside a DataTemplate

WPF provides a handy little method called FindName which you can use to find controls within a given ContentPresenter. Not quite as straightforward as the old favourite FindControl 😉

private ProgressBar GetProgressBar(VideoClip clip) { int index = clips.Items.IndexOf(clip); ListBoxItem selectedItem = clips.ItemContainerGenerator.ContainerFromIndex(index) as ListBoxItem; if (selectedItem == null) return null; DataTemplateKey key = new DataTemplateKey(typeof(VideoClip)); DataTemplate template = base.FindResource(key) as DataTemplate; Border border = VisualTreeHelper.GetChild(selectedItem, 0) as Border; ContentPresenter presenter = border.Child as ContentPresenter; ProgressBar progress = template.FindName("progress", presenter) as ProgressBar; return progress; }

This method allows me to take an object (which is the data type for the DataTemplate) from the list and use it to access the ProgressBar control.

2. Update the ProgressBar from a different thread

Converter converter = new Converter(); converter.OnConvertProgress += delegate(object sender1, ConvertEventArgs args) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate { ProgressBar bar = GetProgressBar(args.Clip); if (bar != null) bar.Value = args.Clip.SaveProgress; } , null); };

Using the Dispatcher I get hold of the specific ProgressBar I want to update and simply set the value.

Advertisements

Tags: , , , , , ,

5 Responses to “WPF: Making good progress”

  1. WPF/Silverlight/XAML Web Links - 2004/04/18 - Rob Relyea - Xamlified Says:

    […] WebPurity's blog: WPF Example of work on another thread that updates progress in UI […]

  2. WPF/Silverlight/XAML Web Links - 2008/04/18 - Rob Relyea - Xamlified Says:

    […] WebPurity's blog: WPF Example of work on another thread that updates progress in UI […]

  3. Quantum Bit Designs » Blog Archive » Design Decisions and Information Overload Says:

    […] https://webpurityltd.wordpress.com/2008/04/15/wpf-making-good-progress/ […]

  4. HOW TO ACCESS A WPF CONTROL WHICH IS LOCATED IN A DATATEMPLATE | Dev102.com Says:

    […] https://webpurityltd.wordpress.com/2008/04/15/wpf-making-good-progress/ – the suggested solution is very specific and not general and it doesn’t work for me! […]

  5. harbans-lal-gera Says:

    Harbans Lal Gera – I know this is off topic but need help with Vista

    Thanks,
    Harbans Lal Gera

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


%d bloggers like this: