[Version 2.0] General Purpose PanesStyleSelector and PanesTemplateSelector

Aug 16, 2012 at 10:11 PM

Hi All,

First of all, thanks a lot for version 2.0 I'm a big fan of MVVM! 

I wasn't completely happy with the PanesStyleSelector and PanesTemplateSelector as implemented in the sample project. It seems like these duties could be handled more generically, so I've implemented a general purpose version and pasted them below. These classes could be included in the core 2.0 codebase if they make sense. I'm not an expert with WPF so it wouldn't surprise me if there is a better way to do this already... but for what its worth here's what I came up with.

    class PanesTemplateSelector : DataTemplateSelector
    {
        public PanesTemplateSelector()
        {
            TemplateList = new List();
        }

        public List TemplateList
        {
            get;
            set;
        }

        public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
        {
            var match = TemplateList.Where(t => t.DataType as Type == item.GetType()).FirstOrDefault();
            if (match != null) return match;
            return base.SelectTemplate(item, container);
        }
    }

    [ContentProperty ("Style")]
    class StyleTemplate
    {
        public object DataType { get; set; }
        public Style Style { get; set; }
    }

    class PanesStyleSelector : StyleSelector
    {
        public PanesStyleSelector ()
        {
            TemplateList = new List();
        }

        public List TemplateList { get; set; }
        
        public override System.Windows.Style SelectStyle(object item, System.Windows.DependencyObject container)
        {
            var match = TemplateList.Where(t => t.DataType as Type == item.GetType()).FirstOrDefault();
            if (match != null) return match.Style;
            return base.SelectStyle(item, container);
        }
    }

These classes can then be used generically from the XAML:

        <avalonDock:DockingManager.LayoutItemTemplateSelector>
            <local:PanesTemplateSelector>
                <local:PanesTemplateSelector.TemplateList>
                    <DataTemplate DataType="{x:Type ViewModels:MyDocumentViewModel}">
                        <local:MyDocumentView />
                    </DataTemplate>
                </local:PanesTemplateSelector.TemplateList>
            </local:PanesTemplateSelector>
        </avalonDock:DockingManager.LayoutItemTemplateSelector>

        <avalonDock:DockingManager.LayoutItemContainerStyleSelector>
            <local:PanesStyleSelector>
                <local:PanesStyleSelector.TemplateList>
                    <local:StyleTemplate DataType="{x:Type ViewModels:MyDocumentViewModel}">
                        <Style TargetType="{x:Type avalonDock:LayoutItem}">
                            <Setter Property="Title" Value="{Binding Model.Title}"/>
                            <!--<Setter Property="ToolTip" Value="{Binding Model.FilePath}"/>
                            <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
                            <Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
                            <Setter Property="ContentId" Value="{Binding Model.ContentId}"/>-->
                        </Style>
                    </local:StyleTemplate>
                </local:PanesStyleSelector.TemplateList>
            </local:PanesStyleSelector>
        </avalonDock:DockingManager.LayoutItemContainerStyleSelector>

Sep 26, 2012 at 4:14 PM

This concept of this is useful, thanks.

Oct 5, 2012 at 5:22 PM

I'm also not a WPF expert but I would like to suggest if it possible to extend this further by having a default selector that can go through the resources and find the DataTemplate that targets the data type of the view model. This way the user does not even have to markup the docking manager template selector and the user just defines the templates as resources.