1
votes

Using Caliburn Micro 1.5.1 I'm trying to get design time bindings to work in a WP8 app. I have created a design time ViewModel which I specify explicitly in the PhoneApplicationPage:

<phone:PhoneApplicationPage
    d:DataContext="{Binding Source={d:DesignInstance Type=designTime:StartPageDesignTimeViewModel, IsDesignTimeCreatable=True}}"
    micro:Bind.AtDesignTime="True"

The page is really no more than a RadDataBoundListBox from Telerik:

<Grid x:Name="ContentPanel">
    <telerikPrimitives:RadDataBoundListBox x:Name="Rooms"  ...>

As you can see, my ViewModel (and design time view model) have a public property named Rooms which I am binding to the ItemsSource collection using the named convention approach. The approach doesn't work at design time, however, unless I add the ItemsSource property

<Grid x:Name="ContentPanel">
    <telerikPrimitives:RadDataBoundListBox x:Name="Rooms" ItemsSource="{Binding Rooms}" ...>

However, when I use ItemsSource binding I lose the CM wire-up magic like SelectedItem. Is there a way to get my bindings to work at design time using the naming conventions approach without modifying the page with anything other than design time attributes?

1

1 Answers

2
votes

Ok, I figured it out. What I was looking for was the ability to overwrite existing bindings at all times. CM is more defensive than that, and so by default it won't replace existing bindings or values for an ItemsControl. This behavior is defined in ConventionManager.cs thusly:

AddElementConvention<ItemsControl>(ItemsControl.ItemsSourceProperty, "DataContext", "Loaded")
.ApplyBinding = (viewModelType, path, property, element, convention) => {
    if (!SetBindingWithoutBindingOrValueOverwrite(viewModelType, path, property, element, convention, ItemsControl.ItemsSourceProperty)) {
        return false;
    }

    ApplyItemTemplate((ItemsControl)element, property);

    return true;
};

What I did to force the framework to always replace the binding was to replace the call to SetBindingWithoutBindingOrValueOverwrite with a direct call to SetBinding in my BootStrapper. So:

ConventionManager.AddElementConvention<ItemsControl>(ItemsControl.ItemsSourceProperty, "DataContext", "Loaded")
             .ApplyBinding = (viewModelType, path, property, element, convention) => {
                                 ConventionManager.SetBinding(viewModelType, path, property, element, convention, ItemsControl.ItemsSourceProperty);

                                 ConventionManager.ApplyItemTemplate((ItemsControl) element, property);
                                 return true;
                             };

(I also had to make this edit to the convention I had added earlier for RadDataBoundListBox)

I can see where someone might want to declaratively force replace an existing binding in some cases. Maybe I'll write a patch...