@ -19,39 +19,57 @@ namespace Perspex.Controls
using Perspex.Controls.Utils ;
using Perspex.Styling ;
/// <summary>
/// Displays a collection of items.
/// </summary>
public class ItemsControl : TemplatedControl , ILogical
{
/// <summary>
/// The default value for the <see cref="ItemsPanel"/> property.
/// </summary>
[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 ( ) ) ;
/// <summary>
/// Defines the <see cref="Items"/> property.
/// </summary>
public static readonly PerspexProperty < IEnumerable > ItemsProperty =
PerspexProperty . Register < ItemsControl , IEnumerable > ( "Items" ) ;
/// <summary>
/// Defines the <see cref="ItemsPanel"/> property.
/// </summary>
public static readonly PerspexProperty < ItemsPanelTemplate > ItemsPanelProperty =
PerspexProperty . Register < ItemsControl , ItemsPanelTemplate > ( "ItemsPanel" , defaultValue : DefaultPanel ) ;
private IItemContainerGenerator itemContainerGenerator ;
private PerspexReadOnlyListView < IVisual , ILogical > logicalChildren =
private PerspexReadOnlyListView < IVisual , ILogical > logicalChildren =
new PerspexReadOnlyListView < IVisual , ILogical > ( x = > ( ILogical ) x ) ;
private IItemsPresenter presenter ;
/// <summary>
/// Initializes static members of the <see cref="ItemsControl"/> class.
/// </summary>
static ItemsControl ( )
{
ItemsProperty . Changed . Subscribe ( e = >
{
var control = e . Sender as ItemsControl ;
control ? . ItemsChanged ( ( IEnumerable ) e . OldValue , ( IEnumerable ) e . NewValue ) ;
} ) ;
ItemsProperty . Changed . AddClassHandler < ItemsControl > ( x = > x . ItemsChanged ) ;
}
/// <summary>
/// Initializes a new instance of the <see cref="ItemsControl"/> class.
/// </summary>
public ItemsControl ( )
{
this . ItemsChanged ( null , null ) ;
this . Classes . Add ( ":empty" ) ;
}
/// <summary>
/// Gets the <see cref="IItemContainerGenerator"/> for the control.
/// </summary>
public IItemContainerGenerator ItemContainerGenerator
{
get
{
@ -64,18 +82,27 @@ namespace Perspex.Controls
}
}
/// <summary>
/// Gets or sets the items to display.
/// </summary>
public IEnumerable Items
{
get { return this . GetValue ( ItemsProperty ) ; }
set { this . SetValue ( ItemsProperty , value ) ; }
}
/// <summary>
/// Gets or sets the panel used to display the items.
/// </summary>
public ItemsPanelTemplate ItemsPanel
{
get { return this . GetValue ( ItemsPanelProperty ) ; }
set { this . SetValue ( ItemsPanelProperty , value ) ; }
}
/// <summary>
/// Gets the items presenter control.
/// </summary>
public IItemsPresenter Presenter
{
get
@ -90,6 +117,12 @@ namespace Perspex.Controls
}
}
/// <summary>
/// Gets the logical children of the control.
/// </summary>
/// <remarks>
/// The logical children of an <see cref="ItemsControl"/> are the item containers.
/// </remarks>
IPerspexReadOnlyList < ILogical > ILogical . LogicalChildren
{
get
@ -99,25 +132,36 @@ namespace Perspex.Controls
}
}
/// <summary>
/// Creates the <see cref="ItemContainerGenerator"/> for the control.
/// </summary>
/// <returns>An <see cref="IItemContainerGenerator"/>.</returns>
protected virtual IItemContainerGenerator CreateItemContainerGenerator ( )
{
return new ItemContainerGenerator ( this ) ;
}
/// <inheritdoc/>
protected override void OnTemplateApplied ( )
{
this . Presenter = this . FindTemplateChild < IItemsPresenter > ( "itemsPresenter" ) ;
}
protected virtual void ItemsChanged ( IEnumerable oldValue , IEnumerable newValue )
/// <summary>
/// Caled when the <see cref="Items"/> property changes.
/// </summary>
/// <param name="e">The event args.</param>
protected virtual void ItemsChanged ( PerspexPropertyChangedEventArgs e )
{
var incc = oldValue as INotifyCollectionChanged ;
var incc = e . O ldValue 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" ) ;
@ -135,6 +179,12 @@ namespace Perspex.Controls
}
}
/// <summary>
/// Called when the <see cref="INotifyCollectionChanged.CollectionChanged"/> event is
/// raised on <see cref="Items"/>.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
protected virtual void ItemsCollectionChanged ( object sender , NotifyCollectionChangedEventArgs e )
{
var collection = sender as ICollection ;