5 changed files with 303 additions and 349 deletions
@ -0,0 +1,217 @@ |
|||
// 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.Specialized; |
|||
using Perspex.Controls.Generators; |
|||
using Perspex.Controls.Templates; |
|||
using Perspex.Styling; |
|||
|
|||
namespace Perspex.Controls.Presenters |
|||
{ |
|||
/// <summary>
|
|||
/// Base class for controls that present items inside an <see cref="ItemsControl"/>.
|
|||
/// </summary>
|
|||
public abstract class ItemsPresenterBase : Control, IItemsPresenter, ITemplatedControl |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the <see cref="Items"/> property.
|
|||
/// </summary>
|
|||
public static readonly DirectProperty<ItemsPresenterBase, IEnumerable> ItemsProperty = |
|||
ItemsControl.ItemsProperty.AddOwner<ItemsPresenterBase>(o => o.Items, (o, v) => o.Items = v); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="ItemsPanel"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<ITemplate<IPanel>> ItemsPanelProperty = |
|||
ItemsControl.ItemsPanelProperty.AddOwner<ItemsPresenterBase>(); |
|||
|
|||
/// <summary>
|
|||
/// Defines the <see cref="MemberSelector"/> property.
|
|||
/// </summary>
|
|||
public static readonly StyledProperty<IMemberSelector> MemberSelectorProperty = |
|||
ItemsControl.MemberSelectorProperty.AddOwner<ItemsPresenterBase>(); |
|||
|
|||
private IEnumerable _items; |
|||
private bool _createdPanel; |
|||
private IItemContainerGenerator _generator; |
|||
|
|||
/// <summary>
|
|||
/// Initializes static members of the <see cref="ItemsPresenter"/> class.
|
|||
/// </summary>
|
|||
static ItemsPresenterBase() |
|||
{ |
|||
TemplatedParentProperty.Changed.AddClassHandler<ItemsPresenterBase>(x => x.TemplatedParentChanged); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the items to be displayed.
|
|||
/// </summary>
|
|||
public IEnumerable Items |
|||
{ |
|||
get |
|||
{ |
|||
return _items; |
|||
} |
|||
|
|||
set |
|||
{ |
|||
if (_createdPanel) |
|||
{ |
|||
INotifyCollectionChanged incc = _items as INotifyCollectionChanged; |
|||
|
|||
if (incc != null) |
|||
{ |
|||
incc.CollectionChanged -= ItemsCollectionChanged; |
|||
} |
|||
} |
|||
|
|||
if (_createdPanel && value != null) |
|||
{ |
|||
INotifyCollectionChanged incc = value as INotifyCollectionChanged; |
|||
|
|||
if (incc != null) |
|||
{ |
|||
incc.CollectionChanged += ItemsCollectionChanged; |
|||
} |
|||
} |
|||
|
|||
SetAndRaise(ItemsProperty, ref _items, value); |
|||
|
|||
if (_createdPanel) |
|||
{ |
|||
ItemsChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the item container generator.
|
|||
/// </summary>
|
|||
public IItemContainerGenerator ItemContainerGenerator |
|||
{ |
|||
get |
|||
{ |
|||
if (_generator == null) |
|||
{ |
|||
var i = TemplatedParent as ItemsControl; |
|||
_generator = (i?.ItemContainerGenerator) ?? new ItemContainerGenerator(this); |
|||
} |
|||
|
|||
return _generator; |
|||
} |
|||
|
|||
internal set |
|||
{ |
|||
if (_generator != null) |
|||
{ |
|||
throw new InvalidOperationException("ItemContainerGenerator already created."); |
|||
} |
|||
|
|||
_generator = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a template which creates the <see cref="Panel"/> used to display the items.
|
|||
/// </summary>
|
|||
public ITemplate<IPanel> ItemsPanel |
|||
{ |
|||
get { return GetValue(ItemsPanelProperty); } |
|||
set { SetValue(ItemsPanelProperty, value); } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects a member from <see cref="Items"/> to use as the list item.
|
|||
/// </summary>
|
|||
public IMemberSelector MemberSelector |
|||
{ |
|||
get { return GetValue(MemberSelectorProperty); } |
|||
set { SetValue(MemberSelectorProperty, value); } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the panel used to display the items.
|
|||
/// </summary>
|
|||
public IPanel Panel |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override sealed void ApplyTemplate() |
|||
{ |
|||
if (!_createdPanel) |
|||
{ |
|||
CreatePanel(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override Size MeasureOverride(Size availableSize) |
|||
{ |
|||
Panel.Measure(availableSize); |
|||
return Panel.DesiredSize; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override Size ArrangeOverride(Size finalSize) |
|||
{ |
|||
Panel.Arrange(new Rect(finalSize)); |
|||
return finalSize; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates the <see cref="Panel"/> when <see cref="ApplyTemplate"/> is called for the first
|
|||
/// time.
|
|||
/// </summary>
|
|||
protected virtual void CreatePanel() |
|||
{ |
|||
Panel = ItemsPanel.Build(); |
|||
Panel.SetValue(TemplatedParentProperty, TemplatedParent); |
|||
|
|||
LogicalChildren.Clear(); |
|||
VisualChildren.Clear(); |
|||
LogicalChildren.Add(Panel); |
|||
VisualChildren.Add(Panel); |
|||
|
|||
_createdPanel = true; |
|||
|
|||
INotifyCollectionChanged incc = Items as INotifyCollectionChanged; |
|||
|
|||
if (incc != null) |
|||
{ |
|||
incc.CollectionChanged += ItemsCollectionChanged; |
|||
} |
|||
|
|||
ItemsChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Called when the items for the presenter change, either because <see cref="Items"/>
|
|||
/// has been set, or the items collection has been modified.
|
|||
/// </summary>
|
|||
/// <param name="e">A description of the change.</param>
|
|||
protected abstract void ItemsChanged(NotifyCollectionChangedEventArgs e); |
|||
|
|||
/// <summary>
|
|||
/// Called when the <see cref="Items"/> collection changes.
|
|||
/// </summary>
|
|||
/// <param name="sender">The sender.</param>
|
|||
/// <param name="e">The event args.</param>
|
|||
private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) |
|||
{ |
|||
if (_createdPanel) |
|||
{ |
|||
ItemsChanged(e); |
|||
} |
|||
} |
|||
|
|||
private void TemplatedParentChanged(PerspexPropertyChangedEventArgs e) |
|||
{ |
|||
(e.NewValue as IItemsPresenterHost)?.RegisterItemsPresenter(this); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue