// ----------------------------------------------------------------------- // // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Controls.Primitives { using System; using System.Linq; using Perspex.Media; using Perspex.Styling; using Splat; public class TemplatedControl : Control, ITemplatedControl { public static readonly PerspexProperty TemplateProperty = PerspexProperty.Register("Template"); private bool templateApplied; static TemplatedControl() { TemplateProperty.Changed.Subscribe(e => { var templatedControl = (TemplatedControl)e.Sender; templatedControl.templateApplied = false; templatedControl.InvalidateMeasure(); }); } public ControlTemplate Template { get { return this.GetValue(TemplateProperty); } set { this.SetValue(TemplateProperty, value); } } public override void Render(IDrawingContext context) { } public sealed override void ApplyTemplate() { if (!this.templateApplied) { this.ClearVisualChildren(); if (this.Template != null) { this.Log().Debug( "Creating template for {0} (#{1:x8})", this.GetType().Name, this.GetHashCode()); var child = this.Template.Build(this); this.AddVisualChild(child); var templateChildren = this.GetVisualDescendents() .OfType() .Where(x => x.TemplatedParent != null); foreach (var i in templateChildren) { i.ApplyTemplate(); } this.OnTemplateApplied(); } this.templateApplied = true; } } protected override Size ArrangeOverride(Size finalSize) { Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control; if (child != null) { child.Arrange(new Rect(finalSize)); return child.ActualSize; } else { return new Size(); } } protected override Size MeasureOverride(Size availableSize) { Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control; if (child != null) { child.Measure(availableSize); return child.DesiredSize.Value; } return new Size(); } protected T FindTemplateChild(string id) where T : Control { return this.GetTemplateControls() .Where(x => x.TemplatedParent == this) .OfType().FirstOrDefault(x => x.Id == id); } protected T GetTemplateChild(string id) where T : Control { var result = this.FindTemplateChild(id); if (result == null) { throw new InvalidOperationException(string.Format( "Could not find template child '{0}' in template for '{1}'.", id, this.GetType().FullName)); } return result; } protected virtual void OnTemplateApplied() { } } }