From f5a856e109768d2e1c7328316a8aaa0f5f01c2c2 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 26 Dec 2014 22:31:22 +0000 Subject: [PATCH] Make ItemsControl items be logical children. --- Perspex.Controls/Control.cs | 4 +- Perspex.Controls/ItemsControl.cs | 43 ++++++++++++++++++- Perspex.Controls/Panel.cs | 9 +++- Perspex.Controls/Presenters/ItemsPresenter.cs | 2 +- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/Perspex.Controls/Control.cs b/Perspex.Controls/Control.cs index 2b5a8b5075..1e4bff5d94 100644 --- a/Perspex.Controls/Control.cs +++ b/Perspex.Controls/Control.cs @@ -38,6 +38,8 @@ namespace Perspex.Controls public static readonly RoutedEvent RequestBringIntoViewEvent = RoutedEvent.Register("RequestBringIntoView", RoutingStrategy.Bubble); + private static readonly IReadOnlyPerspexList EmptyChildren = new SingleItemPerspexList(); + private Classes classes = new Classes(); private DataTemplates dataTemplates; @@ -167,7 +169,7 @@ namespace Perspex.Controls IReadOnlyPerspexList ILogical.LogicalChildren { - get { throw new NotImplementedException(); } + get { return EmptyChildren; } } public void BringIntoView() diff --git a/Perspex.Controls/ItemsControl.cs b/Perspex.Controls/ItemsControl.cs index 1d8d92b8e4..133fa41559 100644 --- a/Perspex.Controls/ItemsControl.cs +++ b/Perspex.Controls/ItemsControl.cs @@ -11,10 +11,13 @@ namespace Perspex.Controls using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; + using Perspex.Collections; using Perspex.Controls.Generators; + using Perspex.Controls.Presenters; using Perspex.Controls.Primitives; + using Perspex.VisualTree; - public class ItemsControl : TemplatedControl + public class ItemsControl : TemplatedControl, ILogical { [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Needs to be before or a NullReferenceException is thrown.")] private static readonly ItemsPanelTemplate DefaultPanel = @@ -28,6 +31,10 @@ namespace Perspex.Controls private ItemContainerGenerator itemContainerGenerator; + private PerspexReadOnlyListView logicalChildren; + + private ItemsPresenter presenter; + public ItemsControl() { this.GetObservableWithHistory(ItemsProperty).Subscribe(this.ItemsChanged); @@ -58,11 +65,45 @@ namespace Perspex.Controls set { this.SetValue(ItemsPanelProperty, value); } } + IReadOnlyPerspexList ILogical.LogicalChildren + { + get + { + if (this.logicalChildren == null) + { + this.logicalChildren = new PerspexReadOnlyListView( + new PerspexList(), + x => (ILogical)x); + } + + return this.logicalChildren; + } + } + protected virtual ItemContainerGenerator CreateItemContainerGenerator() { return new ItemContainerGenerator(this); } + protected override void OnTemplateApplied() + { + if (this.logicalChildren != null) + { + this.logicalChildren.Dispose(); + this.logicalChildren = null; + } + + this.presenter = this.FindTemplateChild("presenter"); + + if (presenter != null) + { + var panel = (IVisual)this.presenter.GetVisualChildren().Single(); + this.logicalChildren = new PerspexReadOnlyListView( + panel.VisualChildren, + x => (ILogical)x); + } + } + private void ItemsChanged(Tuple value) { INotifyPropertyChanged inpc = value.Item1 as INotifyPropertyChanged; diff --git a/Perspex.Controls/Panel.cs b/Perspex.Controls/Panel.cs index d449f4da05..4a1db10ac6 100644 --- a/Perspex.Controls/Panel.cs +++ b/Perspex.Controls/Panel.cs @@ -62,6 +62,13 @@ namespace Perspex.Controls private void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) { + var logicalParent = (Control)this; + + while (logicalParent.TemplatedParent != null) + { + logicalParent = (Control)logicalParent.TemplatedParent; + } + // TODO: Handle Move and Replace. switch (e.Action) { @@ -70,7 +77,7 @@ namespace Perspex.Controls foreach (var child in e.NewItems.OfType()) { - child.Parent = this; + child.Parent = logicalParent; } break; diff --git a/Perspex.Controls/Presenters/ItemsPresenter.cs b/Perspex.Controls/Presenters/ItemsPresenter.cs index 8830122696..b2de51a674 100644 --- a/Perspex.Controls/Presenters/ItemsPresenter.cs +++ b/Perspex.Controls/Presenters/ItemsPresenter.cs @@ -26,7 +26,7 @@ namespace Perspex.Controls.Presenters public ItemsPresenter() { - this.GetObservableWithHistory(ItemsProperty).Skip(1).Subscribe(this.ItemsChanged); + this.GetObservableWithHistory(ItemsProperty).Subscribe(this.ItemsChanged); } public IEnumerable Items