From 1ee1e0b85dda818557aa46031628c1fb8ddc7bec Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 30 Jun 2014 00:34:28 +0200 Subject: [PATCH] Added DataTemplates. --- .../Controls/ImageTests.cs | 1 - Perspex/Controls/ContentPresenter.cs | 58 ++++++++++++++----- Perspex/Controls/Control.cs | 20 +++++++ Perspex/Controls/DataTemplate.cs | 42 ++++++++++++++ Perspex/Controls/DataTemplates.cs | 20 +++++++ Perspex/Perspex.csproj | 3 + Perspex/Themes/Default/ContentControlStyle.cs | 38 ++++++++++++ Perspex/Themes/Default/DefaultTheme.cs | 2 +- TestApplication/Program.cs | 19 +++++- 9 files changed, 185 insertions(+), 18 deletions(-) create mode 100644 Perspex/Controls/DataTemplate.cs create mode 100644 Perspex/Controls/DataTemplates.cs create mode 100644 Perspex/Themes/Default/ContentControlStyle.cs diff --git a/Perspex.Direct2D1.RenderTests/Controls/ImageTests.cs b/Perspex.Direct2D1.RenderTests/Controls/ImageTests.cs index b904150570..83f0c601a6 100644 --- a/Perspex.Direct2D1.RenderTests/Controls/ImageTests.cs +++ b/Perspex.Direct2D1.RenderTests/Controls/ImageTests.cs @@ -9,7 +9,6 @@ namespace Perspex.Direct2D1.RenderTests.Controls using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; using Perspex.Controls; - using Perspex.Layout; using Perspex.Media; using Perspex.Media.Imaging; diff --git a/Perspex/Controls/ContentPresenter.cs b/Perspex/Controls/ContentPresenter.cs index e4a27a5590..a87f6363e9 100644 --- a/Perspex/Controls/ContentPresenter.cs +++ b/Perspex/Controls/ContentPresenter.cs @@ -20,7 +20,7 @@ namespace Perspex.Controls public static readonly PerspexProperty> DataTemplateProperty = PerspexProperty.Register>("DataTemplate"); - private Visual visualChild; + private IVisual visualChild; public ContentPresenter() { @@ -46,18 +46,11 @@ namespace Perspex.Controls set { this.SetValue(ContentProperty, value); } } - public Func DataTemplate - { - get { return this.GetValue(DataTemplateProperty); } - set { this.SetValue(DataTemplateProperty, value); } - } - IEnumerable IVisual.VisualChildren { get { object content = this.Content; - var dataTemplate = this.DataTemplate; if (this.visualChild == null && content != null) { @@ -65,16 +58,21 @@ namespace Perspex.Controls { this.visualChild = (Visual)content; } - else if (dataTemplate != null) - { - this.visualChild = dataTemplate(this); - } else { - this.visualChild = new TextBlock + DataTemplate dataTemplate = this.FindDataTemplate(content); + + if (dataTemplate != null) { - Text = content.ToString(), - }; + this.visualChild = dataTemplate.Build(content); + } + else + { + this.visualChild = new TextBlock + { + Text = content.ToString(), + }; + } } if (this.visualChild != null) @@ -156,5 +154,35 @@ namespace Perspex.Controls return new Size(); } + + private DataTemplate FindDataTemplate(object content) + { + ILogical node = this; + + while (node != null) + { + Control control = node as Control; + + if (control != null) + { + foreach (DataTemplate dt in control.DataTemplates.Reverse()) + { + if (dt.Match(content)) + { + return dt; + } + } + } + + node = node.LogicalParent; + + if (node == null && control != null) + { + node = control.TemplatedParent as ILogical; + } + } + + return null; + } } } diff --git a/Perspex/Controls/Control.cs b/Perspex/Controls/Control.cs index e23df4c4a3..1f9a26afdc 100644 --- a/Perspex/Controls/Control.cs +++ b/Perspex/Controls/Control.cs @@ -40,6 +40,8 @@ namespace Perspex.Controls private Classes classes; + private DataTemplates dataTemplates; + private string id; private Styles styles; @@ -91,6 +93,24 @@ namespace Perspex.Controls } } + public DataTemplates DataTemplates + { + get + { + if (this.dataTemplates == null) + { + this.dataTemplates = new DataTemplates(); + } + + return this.dataTemplates; + } + + set + { + this.dataTemplates = value; + } + } + public double FontSize { get { return this.GetValue(FontSizeProperty); } diff --git a/Perspex/Controls/DataTemplate.cs b/Perspex/Controls/DataTemplate.cs new file mode 100644 index 0000000000..6c15f6b3bd --- /dev/null +++ b/Perspex/Controls/DataTemplate.cs @@ -0,0 +1,42 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Controls +{ + using System; + using System.Reflection; + + public class DataTemplate + { + public DataTemplate(Type type, Func build) + : this(o => type.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo()), build) + { + } + + public DataTemplate(Func match, Func build) + { + this.Match = match; + this.Build = build; + } + + public Func Match { get; private set; } + + public Func Build { get; private set; } + } + + public class DataTemplate : DataTemplate + { + public DataTemplate(Func build) + : base(typeof(T), o => build((T)o)) + { + } + + public DataTemplate(Func match, Func build) + : base(o => (o is T) ? match((T)o) : false, o => build((T)o)) + { + } + } +} diff --git a/Perspex/Controls/DataTemplates.cs b/Perspex/Controls/DataTemplates.cs new file mode 100644 index 0000000000..1f81fde90f --- /dev/null +++ b/Perspex/Controls/DataTemplates.cs @@ -0,0 +1,20 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Controls +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Linq; + using System.Reactive; + using System.Reactive.Subjects; + + public class DataTemplates : PerspexList + { + } +} diff --git a/Perspex/Perspex.csproj b/Perspex/Perspex.csproj index 3f03832332..8395595291 100644 --- a/Perspex/Perspex.csproj +++ b/Perspex/Perspex.csproj @@ -70,6 +70,8 @@ + + @@ -121,6 +123,7 @@ + diff --git a/Perspex/Themes/Default/ContentControlStyle.cs b/Perspex/Themes/Default/ContentControlStyle.cs new file mode 100644 index 0000000000..81aff1e0c6 --- /dev/null +++ b/Perspex/Themes/Default/ContentControlStyle.cs @@ -0,0 +1,38 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Themes.Default +{ + using System.Linq; + using Perspex.Controls; + using Perspex.Media; + using Perspex.Styling; + + public class ContentControlStyle : Styles + { + public ContentControlStyle() + { + this.AddRange(new[] + { + new Style(x => x.OfType()) + { + Setters = new[] + { + new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), + }, + }, + }); + } + + private Control Template(ContentControl control) + { + return new ContentPresenter + { + [~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty], + }; + } + } +} diff --git a/Perspex/Themes/Default/DefaultTheme.cs b/Perspex/Themes/Default/DefaultTheme.cs index abb18a70b7..12452031f9 100644 --- a/Perspex/Themes/Default/DefaultTheme.cs +++ b/Perspex/Themes/Default/DefaultTheme.cs @@ -14,8 +14,8 @@ namespace Perspex.Themes.Default { this.Add(new ButtonStyle()); this.Add(new CheckBoxStyle()); + this.Add(new ContentControlStyle()); this.Add(new TextBoxStyle()); - } } } diff --git a/TestApplication/Program.cs b/TestApplication/Program.cs index 1e820bbb29..9266712d01 100644 --- a/TestApplication/Program.cs +++ b/TestApplication/Program.cs @@ -75,7 +75,24 @@ namespace TestApplication { Source = new Bitmap("github_icon.png"), Width = 200, - } + }, + new ContentControl + { + DataTemplates = new DataTemplates + { + new DataTemplate(o => new Border + { + Background = Brushes.Red, + BorderBrush = Brushes.Black, + BorderThickness = 2, + Content = new TextBlock + { + Text = o, + } + }), + }, + Content = "Data Template", + }, } } };