writing

January 4, 2008 spout writing

“So easy to read, it should be illegal”

Thanks very much "ET" on the Canadian Amazon. I can think of no higher compliment. : )
November 26, 2007 spout writing

C# 3.0 in a Nutshell, LINQPad and Pure Genius

I absolutely love what the Albahari brothers (Joe & Ben) have done with C# 3.0 in a Nutshell. Not only is their prose concise in a way that mine is not, but I have learned a bunch of stuff about LINQ I didn’t know, they built a tool (LINQPad) that lets you experiment with LINQ interactively in a way that the designers of LINQ themselves don’t support and the tool has all kinds of wonderful features that LINQ, SQL and Regular Expression programmers alike will want to use regularly long after they’ve read the book.

And if that weren’t enough, the tool comes with an integrated tree of samples that follow along with the material in the book, teaching the material from another angle and reinforcing it perfectly. It’s pure genius and if I ever write another book, it’s a model I’m going to follow. Very highly recommended.

October 19, 2007 spout writing

Fun With GridView*RowPresenter

Fun With GridView*RowPresenter

I was searching for advanced WPF tree samples the other day and ran into the tree-list-view sample:

Notice how the left-most column does the indenting, while the rest of the columns line up nicely. The code for the tree-view-sample is a little C# and a bunch of sophisticated XAML templates I didn’t understand, so I stripped it down to the bare nubbins to discover what was going on. Assume a simple class holding the data:

class Person {
  List<Person> children = new List<Person>();
  public string Name { get; set; }
  public int Age { get; set; }
  public List<Person> Children { get { return children; } }
}

The juicy bit that makes the tree-list view above possible is the GridViewRowPresenter:

<Window ...
  xmlns:local="clr-namespace:WpfApplication10"
  Title="GridView*RowPresenter Fun">

  <Window.DataContext>
    <local:Person Name="John" Age="13" />
  </Window.DataContext>

  <GridViewRowPresenter Content="{Binding}">
    <GridViewRowPresenter.Columns>
      <!-- NOTE: must explicitly create the collection -->
        <GridViewColumnCollection>
          <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
          <GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}" />
      </GridViewColumnCollection>
    </GridViewRowPresenter.Columns>
  </GridViewRowPresenter>

</Window>

Here, we’re creating an instance of the GridViewRowPresenter, which is the thing that the ListView creates for you if you use the GridView. Here, we’re using it explicitly and setting the columns explicitly, binding it to our data and yielding the following:

Notice that we’re showing a single item, arranged as a row of values according to our column definition above. It’s boring and not at all interactive, at least because we don’t have a header, which we can get with an instance of the GridViewHeaderRowPresenter:

<Window.Resources>
  <GridViewColumnCollection x:Key="columns">
    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
    <GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}" />
  </GridViewColumnCollection>
</Window.Resources>

<StackPanel>
  <!-- NOTE: must share access to same column collection to get shared resizing -->
  <GridViewHeaderRowPresenter Columns="{StaticResource columns}" />
  <GridViewRowPresenter Content="{Binding}" Columns="{StaticResource columns}" />
</StackPanel>

Here we’re creating an instance of the row presenter, passing in a reference to the same columns collection used by the row presenter so that the column sizes and positions are shared between the header row and the row presenters:

If we want more than one piece of data, all we have to do is use an items control with an item template that in turn creates a row presenter for each item in the collection:

<Window.DataContext>
  <x:Array Type="{x:Type local:Person}">
    <local:Person Name="John" Age="13" />
    <local:Person Name="Tom" Age="12" />
  </x:Array>
</Window.DataContext>

<Window.Resources>
  <GridViewColumnCollection x:Key="columns">
    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
    <GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}" />
  </GridViewColumnCollection>
</Window.Resources>

<StackPanel>
  <GridViewHeaderRowPresenter Columns="{StaticResource columns}" />
  <ItemsControl ItemsSource="{Binding}">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <GridViewRowPresenter Content="{Binding}" Columns="{StaticResource columns}" />
      </DataTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
</StackPanel>

Now, we’ve got a stack panel that combines the header to the grid view rows with the grid view rows themselves, one per item in our collection:

Now on a rush of discovery and simplicity, I took the next step to show hierarchical data, hosting the data in a TreeView control and using a hierarchical data template so that I could build the tree list view shown above with the tiniest bit of XAML and code:

<Window.DataContext>
  <x:Array Type="{x:Type local:Person}">
  <local:Person Name="Chris" Age="38">
    <local:Person.Children>
      <local:Person Name="John" Age="13" />
      <local:Person Name="Tom" Age="12" />
    </local:Person.Children>
  </local:Person>
  <local:Person Name="Melissa" Age="39" />
  </x:Array>
</Window.DataContext>
...
<StackPanel>
  <GridViewHeaderRowPresenter Columns="{StaticResource columns}" />
  <TreeView ItemsSource="{Binding}" BorderThickness="0">
    <TreeView.ItemTemplate>
      <HierarchicalDataTemplate ItemsSource="{Binding Children}">
       <GridViewRowPresenter Content="{Binding}" Columns="{StaticResource columns}" />
      </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
  </TreeView>
</StackPanel>

Unfortunately, that’s where we run into the limit of what we can do without cranking things up a notch:

 

Beside the border around the tree view (caused by focus), the worst part about our simple tree-list-view is that, while each grid view row has the proper column sizes and relative positions, because the tree does the indenting, all of the columns are offset, not just the first one. The key to fixing this problem is to put the styling for indenting into the template for the first column only using the CellTemplate property of the GridViewRowColumn, taking over the drawing of the tree view items, which is what the tree-list-view sample does.

August 28, 2007 spout writing

“Programming WPF” (finally) shipping!

John Osborn of O’Reilly and Associates had this to say in my morning email:

Congratulations, guys. The book is printed and shipping! Just got my copy this morning and it looks great. A very substantial body of work, to say the least.

Thanks for all of your hard work on this project. Now to crank up the PR machine and make sure no book shelf is without a copy.”

Wahoo!

August 17, 2007 spout writing

How to write a book - the short honest truth

I found this on digg.com and liked the short, honest style. Bottom line: anyone can write a book; it takes real work to write a good book.
August 14, 2007 spout writing

“How you doin’?”

I wanted to figure out how to emit a new CLR type at run-time using Reflection.Emit and Google revealed the following article: Generating Code at Run Time With Reflection.Emit in DDJ.As usual, I skip most of the initial prose to the first code sample (I don’t need some author’s fancy intro — I just want the code!). Then, I’m reading along and I find some phrases I enjoy, e.g.

If you plan on generating lots of calls to Console.WriteLine(), you should be aware that the ILGenerator class exposes a method for just that purpose: ILGenerator.EmitWriteLine() generates the exact same code as our example. (Could this be the first assembler ever devised that includes explicit support for creating Hello, World” sample programs?)”

and

When creating a dynamic assembly with Reflection.Emit, you must declare, ahead of time, what you plan on doing with it. Do you want to run it or save it? Or both? (Of course, if your answer is neither,’ then you should probably should have stopped reading this article long ago.)”

By the end of the piece, I’ve enjoyed the story and it told me exactly what I wanted and then some, pointing out some pitfalls I would’ve missed, being entertaining along the way. It’s rare that I enjoy an article so much and I’m thinking I should send the author an email, congratulating him/her on his/her tight, fun prose.

And then I get to the author bios:

Chris Sells is a blah blah blah.”

Shawn Van Ness is a blah blah blah.”

Of course, now I remember Shawn writing this piece and me helping him with the polish. At this point, I feel a bit like the Joey Tribbiani of Windows technical writing…

July 17, 2007 spout writing

Programming WPF, 2e (RTM Edition) on Amazon!

Buy your copy today! : )

P.S. I read the QC1 (Quality Check 1), all 859 pages of it, in two solid days this weekend. I found a bunch of nits, all of which will be fixed before you see it in August. Wahoo!

May 28, 2007 spout writing

Why do we pick on journalism majors, so?

Here’s another one:

For example, if we had had a background in journalism, we might have used one-based indexing instead of zero-based indexing to…

That Ian didn’t like, but it still makes me smile (and if you’re not a smiling author, why be an author at all?!?).