Jerry Nixon @Work: Simple Master/Details, Data Bound WPF Sample

Jerry Nixon on Windows

Wednesday, November 26, 2008

Simple Master/Details, Data Bound WPF Sample

It's time to stop ignoring WPF.

Before we do, let's be honest.

Five reasons WPF sucks:

  1. Using Blend (the WPF extra-Visual Studio design tool) is sloppy
  2. Editing raw XAML (like HTML for WinForms) is painfully slow
  3. Cool third party controls are few compared to WinForms
  4. The likelihood of major, forthcoming syntactic changes is high
  5. Samples and real world case studies are rare or absent

Five reasons WPF rocks:

  1. Done right, WPF can create an unmatched user experience
  2. Most WPF development ports to Silverlight without change
  3. Vector-based objects render faster and cleaner than bitmaps
  4. The .Net Framework is the same in WPF or WinForms
  5. Microsoft loves you when you adopt new technologies

Number 5 is real. Microsoft's WinForm support isn't even near sunset; the WinForms and WPF convergence is inevitable and imminent. Microsoft is investing heavily in WPF. Visual Studio 2010 is 100% WPF. That's amazing. Forthcoming applications will continue this.

Frankly, ignoring WPF is foolishness.

Consider HTML. Developers who watched HTML emerge, followed syntactic changes and enhancements more easily/slowly. XAML is young and simple. Follow it now. Train yourself on fundamental syntax and simple adoption of inevitable future enhancements.

WPF isn't going anywhere.  You don't need a blue badge to know WPF is strategic to Microsoft. It's growing in adoption, support, and power. The development experience is not as fast as WinForms today, but it's close. Eventually, they will be in parity.

Would I recommend WPF as a production platform?

Some argue WPF is the most future-oriented technology. Maybe. But developer velocity and maintenance is important. Today's WPF will be different than the next WPF. Deprecation of controls like ListView is an example. WPF needs to compliment other technologies, in my opinion. It would be difficult to recommend WPF as the sole LOB platform. But, that's me.

Now, let's create a simple application.

Here's what you are building -a simple master/detail form:

image

First create a WPF Application project. I called mine WpfApplication1. Clever, huh?

Second, spin up Northwind. Create a Linq to SQL class and add an Employee entity.

image 
Third, create an Employees.cs class. Here's the code: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace WpfApplication1
{
public class Employees
: ObservableCollection<Employee>
{
public Employees()
{
var _Result = from _Employee in
new DatabaseDataContext().Employees
select _Employee;
foreach (var item in _Result)
this.Add(item);
}
}
}

The reason for this class is so you can reference it as a self-filling DataContext from within the XAML. There are PLENTY of other ways to set the DataContext. This is just how I am doing it here. Honestly, I was trying to do it all without any Window1.xaml code behind. Once you understand DataContext, you can do whatever you want.


Forth, edit Window1.xaml. Here's the code: 



<Window x:Class="WpfApplication1.Window1"
x:Name="Window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<DataTemplate x:Key="ListTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding Path=Photo}"
Width="20" Stretch="UniformToFill" />
<Label Grid.Column="1"
Content="{Binding Path=FirstName}" />
<Label Grid.Column="2"
Content="{Binding Path=LastName}" />
</Grid>
</DataTemplate>
</Window.Resources>
<Window.DataContext>
<data:Employees />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox BorderThickness="0"
IsSynchronizedWithCurrentItem="True"
ItemTemplate="{StaticResource ListTemplate}"
ItemsSource="{Binding}" />
<StackPanel Grid.Column="1">
<Image Source="{Binding Path=Photo}"
Stretch="Fill" />
<Label Content="{Binding Path=FirstName}" />
<Label Content="{Binding Path=LastName}" />
<Label Content="{Binding Path=Title}" />
</StackPanel>
</Grid>
</Window>

Not much code, really?


Beautiful. Now hit F5.



There are a lot of neat things here:




  1. <DataTemplate> is used to display the user list and little photo. You can create templates on the page or in external files to be shared by pages/windows.


  2. xmlns:data="clr-namespace:WpfApplication1" is added so I can reference the classes in my project in the XAML of this window (like in the Window.DataContext).


  3. <Window.DataContext> references the structure for binding. The reason you add this in the XAML is the data types and sample data appear in the designer.


  4. IsSynchronizedWithCurrentItem="True" is the tag on the ListBox that indicates the SelectedItem of the control changes the CurrentItem on the CurrencyManger.



Have fun everyone!