using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace JD.SceneExplorer.TemplateSelector
{
///
///
/// Provides a means to specify DataTemplates to be selected from within WPF code
///
public class DynamicTemplateSelector : DataTemplateSelector
{
///
/// Generic attached property specifying s
/// used by the
///
///
/// This attached property will allow you to set the templates you wish to be available whenever
/// a control's TemplateSelector is set to an instance of
///
public static readonly DependencyProperty TemplatesProperty =
DependencyProperty.RegisterAttached("Templates", typeof(TemplateCollection), typeof(DataTemplateSelector),
new FrameworkPropertyMetadata(new TemplateCollection(), FrameworkPropertyMetadataOptions.Inherits));
///
/// Gets the value of the 's attached
///
/// The who's attached template's property you wish to retrieve
/// The templates used by the givem
/// when using the
public static TemplateCollection GetTemplates(UIElement element)
{
return (TemplateCollection)element.GetValue(TemplatesProperty);
}
///
/// Sets the value of the 's attached
///
/// The element to set the property on
/// The collection of s to apply to this element
public static void SetTemplates(UIElement element, TemplateCollection collection)
{
element.SetValue(TemplatesProperty, collection);
}
///
///
/// Overriden base method to allow the selection of the correct DataTemplate
///
/// The item for which the template should be retrieved
/// The object containing the current item
/// The to use when rendering the
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
//This should ensure that the item we are getting is in fact capable of holding our property
//before we attempt to retrieve it.
if (!(container is UIElement))
return base.SelectTemplate(item, container);
//First, we gather all the templates associated with the current control through our dependency property
TemplateCollection templates = GetTemplates(container as UIElement);
if (templates == null || templates.Count == 0)
base.SelectTemplate(item, container);
//Then we go through them checking if any of them match our criteria
foreach (var template in templates)
//In this case, we are checking whether the type of the item
//is the same as the type supported by our DataTemplate
if (template.Value.IsInstanceOfType(item))
//And if it is, then we return that DataTemplate
return template.DataTemplate;
//If all else fails, then we go back to using the default DataTemplate
return base.SelectTemplate(item, container);
}
}
///
///
/// Holds a collection of items
/// for application as a control's DataTemplate.
///
public class TemplateCollection : List
{
}
///
///
/// Provides a link between a value and a
/// for the
///
///
/// In this case, our value is a which we are attempting to match
/// to a
///
public class Template : DependencyObject
{
///
/// Provides the value used to match this to an item
///
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(Type), typeof(Template));
///
/// Provides the used to render items matching the
///
public static readonly DependencyProperty DataTemplateProperty =
DependencyProperty.Register("DataTemplate", typeof(DataTemplate), typeof(Template));
///
/// Gets or Sets the value used to match this to an item
///
public Type Value
{ get { return (Type)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } }
///
/// Gets or Sets the used to render items matching the
///
public DataTemplate DataTemplate
{ get { return (DataTemplate)GetValue(DataTemplateProperty); } set { SetValue(DataTemplateProperty, value); } }
}
}