Friday 31 December 2010

Bonehead

DiceBox seems to be doing pretty well, at least according to the stats coming in from AppHub.

So, as well as the DiceBox 1.1 update, work is underway for an RPG version that is already looking pretty awesome. Unfortunately, its still to early to release any details but a video preview should be available soon. To provide a home on the web for this exciting new endeavour, may I present to you...


The site should be slowly evolving over the following weeks and months, so be sure to keep an eye out.

Thursday 23 December 2010

And now for something completely different: DiceBox

This is bit of a shameless plug really...

Recently a couple of friends and myself have been playing around with the Windows Phone 7 developer tools.

The first fruits of this is DiceBox, a simple dice app, now available on the windows marketplace. If you don't have the Zune software installed you can see the blurb here

Currently there are 6 kinds of dice texture, realistic physics and sound, a total score display and a "shake to roll" feature.

We are planning a series of updates which will introduce a number of additional features, such as backgrounds, shadows and a dice tray for playing poker dice/yahtzee etc

If you have a Windows Phone 7, why not give it a try :)

Monday 8 February 2010

SpatiaLite data provider now in SharpMap trunk

It was nice to see that sussing out how to use those spatial indexes in SpatiaLite was not in vein. A post on bill dollins site prompted me to take a look at the recent changes to the SharpMap trunk, which now includes bills excellent SpatiaLite data provider complete with spatial index support.

Thursday 21 January 2010

WPF Header/Multi-Column ListBox Control



The WPF ListBox control can be used to create a wide variety of user interface elements thanks to templates and styling. However, recently it left me out in the cold...for a while at least.

We had an existing control, based on a heavily styled ListBox, that contained a bunch or items that could be considered as rows in a table. It all worked fine until some bright spark had the idea of adding column headers.

Now, at this point you may be thinking that ListBox is not the ideal candidate here. ListView, with its GridView layout, is the control to use if you want to layout column based data with column headers. Right?

Well, not always. GridView is fine if you want to apply styles to individual cells or columns. The problem with our particular style was that each conceptual row could be expanded in various ways, making the GridView unsuitable. There were two options as far as i could see:

  1. Write a custom View (based on ViewBase) for ListView
  2. Add a header to the ListBox control

We went with option two. The pain began.

The basic problem is that the header needs to be part of the ListBox so that when the ListBox is scrolled horizontally, the header scrolls too. However, when you scroll it Vertically you want the header to remain visible and not scroll with the rest of the list.

I started by looking at the style of the ListView control which does something similar to what i wanted to achieve. This gave me a big clue. The ListView uses a custom ScrollViewer that has a child scrollviewer nested inside. This child ScrollViewer contains the header; The scrollbars on the child ScrollViewer are always hidden. Magic.

I also had a look at this very helpful article: Building a Multi-Column ListBox in Avalon

This came close to what i wanted to achieve, but there were a number of problems:

  • It was written before the first release of WPF and would no longer compile
  • Having updated it so that it did compile, there were several problems with the scrolling resulting in unsatisfactory placement of the vertical scrollbar (not consistent with ListView) and errors causing the content to slide past the header at the extreme right.

Nevertheless, it gave me a lot of ideas, In-fact the example is based on a lot of the same XAML.

Next, I need to work out how to make the header scroll horizontally when the list box is scrolled horizontally. Unfortunately there is no easy way to do this. Ideally you would bind the HorizontalOffset of the header ScrollViewer to that of the main one. However, this is not possible thanks to its read only nature. To overcome this I used an attached behaviour to achieve the same goal by making use of the ScrollToHorizontalOffset method.

The resulting XAML for the ScrollViewer looks like this:

 <Style x:Key="HeaderedScrollViewer" TargetType="{x:Type ScrollViewer}"> 
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Margin="{TemplateBinding Padding}">
<ScrollViewer DockPanel.Dock="Top"
local:SetHorizontalOffset.Offset="{Binding
RelativeSource={RelativeSource TemplatedParent},
Path=HorizontalOffset}"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
Focusable="false"
Content="{StaticResource ListHeader}">
</ScrollViewer>
<ScrollContentPresenter Name="PART_ScrollContentPresenter"
KeyboardNavigation.DirectionalNavigation="Local"/>
</DockPanel>
<ScrollBar Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Value="{TemplateBinding HorizontalOffset}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
<ScrollBar Name="PART_VerticalScrollBar"
Grid.Column="1"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Value="{TemplateBinding VerticalOffset}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

And it is applied to the ListBox with this style:

 <Style x:Key="{x:Type ListBox}" TargetType="{x:Type ListBox}"> 
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ScrollViewer Style="{StaticResource HeaderedScrollViewer}"
Grid.IsSharedSizeScope="True">
<StackPanel IsItemsHost="true"/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

You can download the full source here: MultiColumnList.zip