Telerik RadDiagram and Caliburn.Micro

Topics: Conventions, Framework Services, UI Architecture
Apr 2, 2013 at 4:42 PM
Edited Apr 2, 2013 at 4:43 PM
Hi all,

I've been banging my head against the wall with using CB.M with Telerik's RadDiagram framework and was wondering if anyone has any advice. You can read my original post here. Below is a copy of the forum post.

I'm really trying not to fall into the "code-behind" coding style as I've seen the pitfalls for years in Winforms, ASP, etc. I'd like to think that I've learned from my mistakes and like how MVVM helps to enforce separation of concerns.

If anyone has experience with using the Telerik RadDiagram with Caliburn.Micro, I'd love to hear from you! Thank you.

Hello all,

I have been trying to implement RadDiagram in an MVVM way, using Caliburn.Micro and I'm coming to the conclusion that this just doesn't fit well with the Telerik controls architecture. I would love it if someone can prove me wrong.

I've looked at every sample app from these forums and Telerik's help, often confused at the reams of <style> code I have to wade through to make sense of anything, and I've still not found a simple answer to my issues.

The following are my goals:
  • Use UserControls, not Styles, to implement my shapes
    • I like that the UserControls can easily be designed in Blend or Visual Studio
    • I like that the visual implementation is modular within each UserControl
    • unless someone can propose an elegant, organized solution using styles/ResourceDictionaries
  • Use MVVM architecture and Caliburn.Micro to locate views for the viewmodels (viewmodel-first approach)
    • All the examples of MVVM implementation I've seen seem clunky, but maybe I'm just not seeing the forest through the trees.
  • Have multiple custom shapes on a RadDiagram
    • Unless I'm missing something, it appears that you must override the Template for type:RadDiagramShape to show your custom control visual. I don't like having this xaml mixed in with the main RadDiagram xaml. I'd like to separate it into the custom shape xaml for clarity.
    • it also appears that I need to create a custom RadDiagram control and override IsItemItsOwnShapeContainerOverride (etc),
      instantiating each custom shape depending on the type of the object passed in.
At this point, I'm so confused by the myriad of examples of ways to implement things, that I'm looking for a very simple example of complete view/viewmodel separation (no code behind, unless just to set the viewmodel, if not using an MVVM framework), multiple custom shapes support, well-organized xaml/code into meaningful, logical files that can be designed in VS or Blend.

I'm also willing to admit that maybe I'm just missing something that brings everything together nicely. I hope someone can point me in the right direction.

Apr 2, 2013 at 8:56 PM
Edited Apr 3, 2013 at 10:04 PM
** removed invalid example as the issue still existed **
Apr 3, 2013 at 5:13 PM
I spoke too soon. The Copy/Paste doesn't work 100% as the RadDiagramShape doesn't get the proper DataContext the way things are wired up.

If I figure this out, I'll post a solution in case anyone else is interested.
Apr 3, 2013 at 10:03 PM
Telerik got back to my question with a TemplateSelector solution, completely ignoring the Caliburn.Micro component. I'd rather not use what feels like a very "code duplication" approach. I'd like to leverage CM as I feel it reduces a lot of the tedious duplication of code, but without the source (yet) for the RadDiagram, I'm at a loss why Caliburn can't resolve the view for the ViewModel when copy/pasting a Shape.

From the Telerik sample, it appears that the copy/paste does a Serialize/Deserialize of the shape (see MainWindow.xaml.cs below), then CM can't resolve the view at that time.

If someone could take a look at the sample code and advise, I would be very grateful.

The views are simple UserControls and the DataTemplates defined in MainWindow.xaml are selected by the ShapeTemplateSelector. What I'd like to be able to do is replace the numerous DataTemplate/UserControl definitions with a single <ContentControl cal:View.Model="{Binding} />, but I'm not sure how to configure CM or what to call in the diagram_ShapeDeserialized_1 / diagram_ShapeSerialized_1 event handlers for the RadDiagram.

<Window x:Class="DiagramMVVM_UserControls.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="rootGrid">
            <Style TargetType="telerik:RadDiagramShape">
                <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" />
                <Setter Property="Padding" Value="0" />
                <Setter Property="IsResizingEnabled" Value="False" />
            <Style TargetType="telerik:RadDiagramConnection">
                <Setter Property="ContentTemplate" >
                        <DataTemplate />
            <DataTemplate x:Key="gridViewTemplate">
                <views:GridViewUserControl />

            <DataTemplate x:Key="treeViewTemplate">
                <views:TreeViewUserControl />

           <DataTemplate x:Key="progressBarTemplate">
                    <views:ProgressBarUserControl />
            <local:ShapeTemplateSelector x:Key="shapeTemplateSelector"
                                         GridViewTemplate="{StaticResource gridViewTemplate}"
                                         TreeViewTemplate="{StaticResource treeViewTemplate}"
                                         ProgressBarTemplate="{StaticResource progressBarTemplate}" />
        <telerik:RadDiagram ShapeTemplateSelector="{StaticResource shapeTemplateSelector}"
using System.Collections.ObjectModel;
using System.Windows;
using DiagramMVVM_UserControls.ViewModels;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.Diagrams;
using Telerik.Windows.Controls.Diagrams.Extensions.ViewModels;

namespace DiagramMVVM_UserControls
    /// <summary>
    ///   Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
        public MainWindow()

        private void BindDiagram()
            var source = new GraphSource();
            var gridModel = new GridViewViewModel
                                Position = new Point(0, 200)
            gridModel.GridItems = new ObservableCollection<string>
            var treeModel = new TreeViewViewModel
                                Position = new Point(300, 50)
            treeModel.TreeItems = new ObservableCollection<string>
                                      "tree item A",
                                      "tree item B",
                                      "tree item C",
                                      "tree item D"
            var progressModel = new ProgressBarViewModel
                                    Position = new Point(500, 100)

            source.AddLink(new LinkViewModelBase<NodeViewModelBase>(gridModel, treeModel));
            source.AddLink(new LinkViewModelBase<NodeViewModelBase>(treeModel, progressModel));

            this.diagram.GraphSource = source;

        private void diagram_ShapeDeserialized_1(object sender, ShapeSerializationRoutedEventArgs e)
            if (e.SerializationInfo["DataContextType"].ToString() == "ProgressBarViewModel")
                (e.Shape as RadDiagramShape).DataContext = new ProgressBarViewModel();
                (e.Shape as RadDiagramShape).ContentTemplate = this.rootGrid.Resources["progressBarTemplate"] as DataTemplate;

        private void diagram_ShapeSerialized_1(object sender, ShapeSerializationRoutedEventArgs e)
            if ((e.Shape as RadDiagramShape).DataContext is ProgressBarViewModel)
                e.SerializationInfo["DataContextType"] = "ProgressBarViewModel";
using System.Windows;
using System.Windows.Controls;
using DiagramMVVM_UserControls.ViewModels;

namespace DiagramMVVM_UserControls
    public class ShapeTemplateSelector : DataTemplateSelector
        public DataTemplate GridViewTemplate { get; set; }
        public DataTemplate TreeViewTemplate { get; set; }
        public DataTemplate ProgressBarTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
            if (item is GridViewViewModel) return this.GridViewTemplate;
            else if (item is TreeViewViewModel) return this.TreeViewTemplate;
            else if (item is ProgressBarViewModel) return this.ProgressBarTemplate;

            return base.SelectTemplate(item, container);