IanG on Tap

Ian Griffiths in Weblog Form (RSS 2.0)

Blog Navigation

April (2018)

(1 item)

August (2014)

(1 item)

July (2014)

(5 items)

April (2014)

(1 item)

March (2014)

(1 item)

January (2014)

(2 items)

November (2013)

(2 items)

July (2013)

(4 items)

April (2013)

(1 item)

February (2013)

(6 items)

September (2011)

(2 items)

November (2010)

(4 items)

September (2010)

(1 item)

August (2010)

(4 items)

July (2010)

(2 items)

September (2009)

(1 item)

June (2009)

(1 item)

April (2009)

(1 item)

November (2008)

(1 item)

October (2008)

(1 item)

September (2008)

(1 item)

July (2008)

(1 item)

June (2008)

(1 item)

May (2008)

(2 items)

April (2008)

(2 items)

March (2008)

(5 items)

January (2008)

(3 items)

December (2007)

(1 item)

November (2007)

(1 item)

October (2007)

(1 item)

September (2007)

(3 items)

August (2007)

(1 item)

July (2007)

(1 item)

June (2007)

(2 items)

May (2007)

(8 items)

April (2007)

(2 items)

March (2007)

(7 items)

February (2007)

(2 items)

January (2007)

(2 items)

November (2006)

(1 item)

October (2006)

(2 items)

September (2006)

(1 item)

June (2006)

(2 items)

May (2006)

(4 items)

April (2006)

(1 item)

March (2006)

(5 items)

January (2006)

(1 item)

December (2005)

(3 items)

November (2005)

(2 items)

October (2005)

(2 items)

September (2005)

(8 items)

August (2005)

(7 items)

June (2005)

(3 items)

May (2005)

(7 items)

April (2005)

(6 items)

March (2005)

(1 item)

February (2005)

(2 items)

January (2005)

(5 items)

December (2004)

(5 items)

November (2004)

(7 items)

October (2004)

(3 items)

September (2004)

(7 items)

August (2004)

(16 items)

July (2004)

(10 items)

June (2004)

(27 items)

May (2004)

(15 items)

April (2004)

(15 items)

March (2004)

(13 items)

February (2004)

(16 items)

January (2004)

(15 items)

Blog Home

RSS 2.0

Writing

Programming C# 5.0

Programming WPF

Other Sites

Interact Software

WPF Data Binding: Harmonic Series Visualization

Sunday 19 November, 2006, 10:27 AM

Recently I was speaking at TechEd Europe. One of my talks was on WPF data binding, and I wanted to show some of the things that make WPF data binding different from Windows Forms. So I wrote a little demo that shows a couple of interesting data binding techniques: user interface generation, and graphical data visualization.

The demo looks like this:

WPF application showing a waveform and 10 slider controls

The application lets you build a waveform from a harmonic series. The sliders on the right control the amplitudes of the harmonics, and the screen area on the left displays the result. The wave is updated continuously: you can see the wave shape change as you drag the sliders around. This screen shot shows the fundamental at maximum amplitude, with the 8th harmonic added in at a lower amplitude. This results in the overall shape roughly following a single cycle of a sine wave, but with higher frequency wiggles superposed. Given enough harmonics you can recreate any repeating wave form if you get the right set of amplitudes.

The application uses data binding in three different ways. The most striking is the waveform output. Here's the XAML I used:

<Polyline Stroke="#48F" StrokeThickness="1.5"
    Points="{Binding Output,
            Converter={StaticResource pointConverter}}"
    Canvas.Top="50" />

Polyline is a graphical element that renders a line that passes through many points. This is bound to the Output propery of the UI's DataContext, which holds an instance of a class I wrote called HarmonicSeries. Here's the Output property:

public double[] Output
{
    get { return outputValues; }
}

Pretty straightforward really. The HarmonicSeries class implements the INotifyPropertyChanged interface, raising the PropertyChanged event every time it recalculates the output wave. Besides that, it does nothing to help the UI. HarmonicSeries contains no WPF-specific features.

But how does binding this property to Polyline.Points work? That property expects a PointCollection, not a double array. The answer is that I'm using a value converter. My project contains a class that converts from a double array to a PointCollection, and I told the Binding to use that. So it simply calls that code every time it reads a new set of points from the Output property.

You might want to check out a couple of other blogs that show various takes on binding to a Polyline. Beatriz Costa is a PM on the WPF data binding team, and she wrote a series of blog entries on this: part 1, part 2, and part 3. Zhou Yong takes a somewhat different approach, writing a class that wraps the underlying data with a dependency property as well as converting it. (Note that while one of the benefits Zhou Yong shows with his approach is that he doesn't need to do the explicit call to Measure and Arrange. However, my approach didn't seem to need that either. I think that issue was specific to the second of Beatriz's examples.)

The second place I'm using data binding is a little more subtle. I'll show you the data source property before I show you the binding. This is another property on the HarmonicSeries class:

public Amplitude[] Amplitudes
{
    get { return amplitudeValues; }
}

This stores the amplitude for each harmonic. Amplitude is another class in the project, and a desperately simple one: it's just wraps an INotifyPropertyChanged implementation around a double. Initially I thought I'd be able to use an ObservableCollection of doubles, but that turns out to be backwards: what I need is a collection of observable doubles, which is not the same thing. So, bearing that in mind, now let's look at the next two data binding expressions:

<ItemsControl x:Name="amplitudeSliders" Grid.Column="1"
              ItemsSource="{Binding Amplitudes}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Slider Minimum="0" Maximum="1" Value="{Binding Value}"
              SmallChange="0.01" LargeChange="0.1" />
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl> 

This is the markup for the right hand side of the UI. That's all of it - this generates all ten Slider controls. I'm using the ItemsControl to perform this generation. ItemsControl is the base class of controls like ListBox, ComboBox, TreeView etc. It provides the basic item generation and data binding support, and the derived list controls then add the standard behaviours for these common controls. But you can just use the base class itself. I'm using it to bind to the amplitudes, generating an instance of the DataTemplate for each amplitude in the source.

The third place I'm using data binding is the generated slider itself. It's straightforward: it just binds to the Value in the Amplitude class. The one moderately interesting thing about this is that each instance of the DataTemplate will have its DataContext set to the source item for which it's being generated, i.e. the relevant Amplitude object. This is why I'm able to use a Binding expression inside of a the UI that was generated by data binding. It's more common to see bindings in data templates used simply to display data, or perhaps to hook up a TextBox. I wanted to show a slightly less common example. And I thought this visual illustration of the point was more fun than illustrating the same concepts with dry text controls.

If you were at TechEd Europe this year, you should already have this demo. For everyone else, you can download the source and binary from here: WaveData.zip.

Copyright © 2002-2024, Interact Software Ltd. Content by Ian Griffiths. Please direct all Web site inquiries to webmaster@interact-sw.co.uk