开发者

Caliburn.Micro & Telerik WPF Controls

Hope you're all well.

I am using Caliburn.Micro with Telerik's WPF controls to build a tabbed interface. Using RadTabControl I have the following code;

<telerik:RadTabControl x:Name="Items" Grid.Row="1" TabStripPlacement="Bottom">
    <telerik:RadTabControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Im开发者_如何学Cage Source="{Binding DisplayIcon}" Width="16" Height="16"/>
                <TextBlock Text="{Binding DisplayName}"/>
            </StackPanel>
        </DataTemplate>
    </telerik:RadTabControl.ItemTemplate>
</telerik:RadTabControl>

The tab has the correct header but the contents read ".../MyViewModel" (ellipses replace full path) instead of the Screen that should be displayed.

If I replace <telerik:RadTabControl... with <TabControl... this all works as intended.

What am I missing?


Caliburn's conventions system is only configured for WPF controls that are out-of-the-box. When it sees the RabTabControl, it doesn't recognize it, so it searched it's class hierarchy looking for something it does recognize. In this case, it probably matches on either Selector or ItemsControl. This is why there is a partial application of conventions. In order to get exactly what you want, you need to add a convention to the ConventionManager for RadTabControl that does exactly what you want. Here is how the TabControl convention is defined:

AddElementConvention<TabControl>(TabControl.ItemsSourceProperty, "ItemsSource", "SelectionChanged")
.ApplyBinding = (viewModelType, path, property, element, convention) => {
    if(!SetBinding(viewModelType, path, property, element, convention))
        return;

    var tabControl = (TabControl)element;
    if(tabControl.ContentTemplate == null && tabControl.ContentTemplateSelector == null && property.PropertyType.IsGenericType) {
        var itemType = property.PropertyType.GetGenericArguments().First();
        if(!itemType.IsValueType && !typeof(string).IsAssignableFrom(itemType))
            tabControl.ContentTemplate = DefaultItemTemplate;
    }

    ConfigureSelectedItem(element, Selector.SelectedItemProperty, viewModelType, path);

    if(string.IsNullOrEmpty(tabControl.DisplayMemberPath))
        ApplyHeaderTemplate(tabControl, TabControl.ItemTemplateProperty, viewModelType);
};

I think you should be able to take the code and with a few minor modifications, make it do what you want. Note that some of the methods called in the above code actually exist on the ConventionManager, so you will need to fix that up. You should add your convention in your Bootstrapper's Configure override. For an additional sample of this, have a look at the WP7 template's Bootstrapper, which defines custom conventions for Pivot and Panarama.


Caliburn.Micro.Telerik contains conventions for Telerik's WPF controls, as well as some other Telerik+WPF specific stuff like an IWindowManager implementation and two applications with examples.

You can check out the source code or the nuget package.

The convention for RadTabControl looks like this:

ConventionManager.AddElementConvention<RadTabControl>(RadTabControl.ItemsSourceProperty,
                                                  "ItemsSource",
                                                  "SelectionChanged")
.ApplyBinding = (viewModelType, path, property, element, convention) =>
{
    if (!ConventionManager.SetBindingWithoutBindingOrValueOverwrite(viewModelType,
                                                                    path,
                                                                    property,
                                                                    element,
                                                                    convention,
                                                                    RadTabControl.ItemsSourceProperty))
        return false;

    var tabControl = (RadTabControl) element;
    if (tabControl.ContentTemplate == null
        && tabControl.ContentTemplateSelector == null
        && property.PropertyType.IsGenericType)
    {
        var itemType = property.PropertyType.GetGenericArguments().First();
        if (!itemType.IsValueType && !typeof (string).IsAssignableFrom(itemType))
            tabControl.ContentTemplate = ConventionManager.DefaultItemTemplate;
    }
    ConventionManager.ConfigureSelectedItem(element,
                                            RadTabControl.SelectedItemProperty,
                                            viewModelType,
                                            path);

    if (string.IsNullOrEmpty(tabControl.DisplayMemberPath))
        ConventionManager.ApplyHeaderTemplate(tabControl,
                                              RadTabControl.ItemTemplateProperty,
                                              RadTabControl.ItemTemplateSelectorProperty,
                                              viewModelType);
    return true;
};

Hope this helps...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜