// ----------------------------------------------------------------------- // // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Controls { using System; using System.Collections; 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; /// /// 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 ItemsPanelTemplate DefaultPanel = new ItemsPanelTemplate(() => new StackPanel()); /// /// Defines the property. /// public static readonly PerspexProperty ItemsProperty = PerspexProperty.Register("Items"); /// /// Defines the property. /// public static readonly PerspexProperty ItemsPanelProperty = PerspexProperty.Register("ItemsPanel", defaultValue: DefaultPanel); 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() { this.Classes.Add(":empty"); } /// /// Gets the for the control. /// public IItemContainerGenerator ItemContainerGenerator { get { if (this.itemContainerGenerator == null) { this.itemContainerGenerator = this.CreateItemContainerGenerator(); } return this.itemContainerGenerator; } } /// /// Gets or sets the items to display. /// public IEnumerable Items { get { return this.GetValue(ItemsProperty); } set { this.SetValue(ItemsProperty, value); } } /// /// Gets or sets the panel used to display the items. /// public ItemsPanelTemplate ItemsPanel { get { return this.GetValue(ItemsPanelProperty); } set { this.SetValue(ItemsPanelProperty, value); } } /// /// Gets the items presenter control. /// public IItemsPresenter Presenter { get; set; } /// IPerspexList IReparentingHost.LogicalChildren { get { return this.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() { this.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 += this.ItemsCollectionChanged; } var newValue = e.NewValue as IEnumerable; if (newValue == null || newValue.Count() == 0) { this.Classes.Add(":empty"); } else { this.Classes.Remove(":empty"); } incc = newValue as INotifyCollectionChanged; if (incc != null) { incc.CollectionChanged += this.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) { this.Classes.Add(":empty"); } else { this.Classes.Remove(":empty"); } } } }