Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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">
                <Image 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?

like image 410
Dan Avatar asked Nov 06 '10 13:11

Dan


People also ask

What is caliburn micro used for?

Caliburn. Micro is a small, yet powerful framework, designed for building applications across all XAML platforms.

Is caliburn micro open source?

Caliburn. Micro is an open source framework licensed under the MIT License and hosted on GitHub.

What is Prism MVVM?

Prism provides an implementation of a collection of design patterns that are helpful in writing well-structured and maintainable XAML applications, including MVVM, dependency injection, commands, EventAggregator, and others. Prism's core functionality is a shared code base in a Cross Compiled .


2 Answers

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.

like image 192
EisenbergEffect Avatar answered Sep 28 '22 04:09

EisenbergEffect


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...

like image 41
Valeriu Caraulean Avatar answered Sep 28 '22 03:09

Valeriu Caraulean