// Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; using System.Collections; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; using System.Linq; using Perspex.Collections; using Perspex.Controls.Generators; using Perspex.Controls.Presenters; using Perspex.Controls.Primitives; using Perspex.Controls.Templates; using Perspex.Controls.Utils; using Perspex.Styling; namespace Perspex.Controls { /// /// Displays a collection of items. /// public class ItemsControl : TemplatedControl, IReparentingHost { /// /// The default value for the property. /// [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Needs to be before or a NullReferenceException is thrown.")] private static readonly FuncTemplate DefaultPanel = new FuncTemplate(() => new StackPanel()); /// /// Defines the property. /// public static readonly PerspexProperty ItemsProperty = PerspexProperty.Register(nameof(Items)); /// /// Defines the property. /// public static readonly PerspexProperty> ItemsPanelProperty = PerspexProperty.Register>(nameof(ItemsPanel), DefaultPanel); /// /// Defines the property. /// public static readonly PerspexProperty MemberSelectorProperty = PerspexProperty.Register(nameof(MemberSelector)); private IItemContainerGenerator _itemContainerGenerator; /// /// Initializes static members of the class. /// static ItemsControl() { ItemsProperty.Changed.AddClassHandler(x => x.ItemsChanged); } /// /// Initializes a new instance of the class. /// public ItemsControl() { Classes.Add(":empty"); Items = new PerspexList(); } /// /// Gets the for the control. /// public IItemContainerGenerator ItemContainerGenerator { get { if (_itemContainerGenerator == null) { _itemContainerGenerator = CreateItemContainerGenerator(); } return _itemContainerGenerator; } } /// /// Gets or sets the items to display. /// public IEnumerable Items { get { return GetValue(ItemsProperty); } set { SetValue(ItemsProperty, value); } } /// /// Gets or sets the panel used to display the items. /// public ITemplate ItemsPanel { get { return GetValue(ItemsPanelProperty); } set { SetValue(ItemsPanelProperty, value); } } /// /// Selects a member from to use as the list item. /// public IMemberSelector MemberSelector { get { return GetValue(MemberSelectorProperty); } set { SetValue(MemberSelectorProperty, value); } } /// /// Gets the items presenter control. /// public IItemsPresenter Presenter { get; set; } /// IPerspexList IReparentingHost.LogicalChildren => LogicalChildren; /// /// Asks the control whether it wants to reparent the logical children of the specified /// control. /// /// The control. /// /// True if the control wants to reparent its logical children otherwise false. /// bool IReparentingHost.WillReparentChildrenOf(IControl control) { return control is IItemsPresenter && control.TemplatedParent == this; } /// /// Creates the for the control. /// /// An . protected virtual IItemContainerGenerator CreateItemContainerGenerator() { return new ItemContainerGenerator(this); } /// protected override void OnTemplateApplied() { Presenter = this.FindTemplateChild("itemsPresenter"); } /// /// Caled when the property changes. /// /// The event args. protected virtual void ItemsChanged(PerspexPropertyChangedEventArgs e) { var incc = e.OldValue as INotifyCollectionChanged; if (incc != null) { incc.CollectionChanged += ItemsCollectionChanged; } var newValue = e.NewValue as IEnumerable; if (newValue == null || newValue.Count() == 0) { Classes.Add(":empty"); } else { Classes.Remove(":empty"); } incc = newValue as INotifyCollectionChanged; if (incc != null) { incc.CollectionChanged += ItemsCollectionChanged; } } /// /// Called when the event is /// raised on . /// /// The event sender. /// The event args. protected virtual void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { var collection = sender as ICollection; if (collection.Count == 0) { Classes.Add(":empty"); } else { Classes.Remove(":empty"); } } } }