The Stochastic Game
Ramblings of General Geekery

Fixing a bug can cause bugs

Microsoft apparently fixed something in .NET Framework 3.5 Service Pack 1 that previously didn’t work, or somehow worked differently. As a result, Milkify will crash if used on a machine that doesn’t have this service pack installed.

What you get is a XamlParseException that says that a ContentStringFormat property cannot be converted into a TemplateBindingExtension. This is because Milkify is using its own WPF skin where, among others, the check box control has a new custom template. This template is mainly a copy of the default one, courtesy of ShowMeTheTemplate, and looks like this:

<ControlTemplate x:Key="CheckBoxControlTemplate">
    <BulletDecorator>
        <BulletDecorator.Bullet>
            <Grid>
                <Border 
                  Width="18"
                  Height="18" 
                  CornerRadius="4"
                  BorderThickness="2"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  Background="{StaticResource MilkifyWhite}"
                  HorizontalAlignment="Center" 
                  VerticalAlignment="Center" />
                <Rectangle
                  Width="6"
                  Height="6"
                  Fill="Black" 
                  Name="RectCheck"
                  HorizontalAlignment="Center" 
                  VerticalAlignment="Center" />
            </Grid>
        </BulletDecorator.Bullet>
        <ContentPresenter 
          RecognizesAccessKey="True" 
          Content="{TemplateBinding ContentControl.Content}" 
          ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" 
          ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" 
          Margin="{TemplateBinding Control.Padding}" 
          HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" 
          VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" 
          SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
    </BulletDecorator>
    <ControlTemplate.Triggers>
        <Trigger Property="CheckBox.IsChecked" Value="False">
            <Setter TargetName="RectCheck" Property="Visibility" Value="Hidden" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Note how the ContentPresenter control defines ContentStringFormat so that it uses whatever string format has been defined on the actual, instanced, check box. Of course, my main programming machine has SP1 installed so it worked fine.

Anyway, for some reason, this works in .NET 3.5 SP1, but not on plain default .NET 3.5. I can’t find much in the documentation about changes brought by SP1 that would explain why it behaves differently, and I don’t think it’s possible to tell ClickOnce that SP1 is a prerequisite to my application (you can only specify .NET 3.5 or not). I could remove that attribute completely, as I never specify it anyway, but it’s not the ideal solution…