19 changed files with 665 additions and 322 deletions
@ -0,0 +1,16 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="IReadOnlyPerspexList.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex |
|||
{ |
|||
using System.Collections.Generic; |
|||
using System.Collections.Specialized; |
|||
using System.ComponentModel; |
|||
|
|||
public interface IReadOnlyPerspexList<T> : IReadOnlyList<T>, INotifyCollectionChanged, INotifyPropertyChanged |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="DataTemplateExtensions.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Controls |
|||
{ |
|||
using System.Linq; |
|||
using Splat; |
|||
|
|||
public static class DataTemplateExtensions |
|||
{ |
|||
public static Control ApplyDataTemplate(this Control control, object data) |
|||
{ |
|||
DataTemplate result = control.FindDataTemplate(data); |
|||
|
|||
if (result != null) |
|||
{ |
|||
return result.Build(data); |
|||
} |
|||
else if (data is Control) |
|||
{ |
|||
return (Control)data; |
|||
} |
|||
else |
|||
{ |
|||
return DataTemplate.Default.Build(data); |
|||
} |
|||
} |
|||
|
|||
public static DataTemplate FindDataTemplate(this Control control, object data) |
|||
{ |
|||
// TODO: This needs to traverse the logical tree, not the visual.
|
|||
foreach (var i in control.GetSelfAndVisualAncestors().OfType<Control>()) |
|||
{ |
|||
foreach (DataTemplate dt in i.DataTemplates.Reverse()) |
|||
{ |
|||
if (dt.Match(data)) |
|||
{ |
|||
return dt; |
|||
} |
|||
} |
|||
} |
|||
|
|||
IGlobalDataTemplates global = Locator.Current.GetService<IGlobalDataTemplates>(); |
|||
|
|||
if (global != null) |
|||
{ |
|||
foreach (DataTemplate dt in global.DataTemplates.Reverse()) |
|||
{ |
|||
if (dt.Match(data)) |
|||
{ |
|||
return dt; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="IItemContainerGenerator.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Controls.Generators |
|||
{ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
|
|||
public enum ItemContainerGeneratorState |
|||
{ |
|||
NoStarted, |
|||
Generating, |
|||
Generated, |
|||
} |
|||
|
|||
public interface IItemContainerGenerator |
|||
{ |
|||
event EventHandler StateChanged; |
|||
|
|||
ItemContainerGeneratorState State { get; } |
|||
|
|||
Control GetContainerForItem(object item); |
|||
|
|||
object GetItemForContainer(Control container); |
|||
|
|||
IEnumerable<Tuple<object, Control>> GetAll(); |
|||
|
|||
IEnumerable<Control> Generate(IEnumerable items); |
|||
|
|||
IEnumerable<Control> Remove(IEnumerable item); |
|||
|
|||
void RemoveAll(); |
|||
} |
|||
} |
|||
@ -0,0 +1,126 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="ItemContainerGenerator.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Controls.Generators |
|||
{ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
public class ItemContainerGenerator : IItemContainerGenerator |
|||
{ |
|||
private Dictionary<object, Control> containersByItem = new Dictionary<object, Control>(); |
|||
|
|||
private Dictionary<Control, object> itemsByContainer = new Dictionary<Control, object>(); |
|||
|
|||
private ItemContainerGeneratorState state; |
|||
|
|||
public ItemContainerGenerator(ItemsControl owner) |
|||
{ |
|||
this.Owner = owner; |
|||
} |
|||
|
|||
public event EventHandler StateChanged; |
|||
|
|||
public ItemContainerGeneratorState State |
|||
{ |
|||
get |
|||
{ |
|||
return this.state; |
|||
} |
|||
|
|||
set |
|||
{ |
|||
if (this.state != value) |
|||
{ |
|||
this.state = value; |
|||
|
|||
if (this.StateChanged != null) |
|||
{ |
|||
this.StateChanged(this, EventArgs.Empty); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected ItemsControl Owner |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
public Control GetContainerForItem(object item) |
|||
{ |
|||
Control result; |
|||
this.containersByItem.TryGetValue(item, out result); |
|||
return result; |
|||
} |
|||
|
|||
public object GetItemForContainer(Control container) |
|||
{ |
|||
object result; |
|||
this.itemsByContainer.TryGetValue(container, out result); |
|||
return result; |
|||
} |
|||
|
|||
public IEnumerable<Tuple<object, Control>> GetAll() |
|||
{ |
|||
return this.containersByItem.Select(x => Tuple.Create(x.Key, x.Value)); |
|||
} |
|||
|
|||
IEnumerable<Control> IItemContainerGenerator.Generate(IEnumerable items) |
|||
{ |
|||
List<Control> result = new List<Control>(); |
|||
|
|||
this.State = ItemContainerGeneratorState.Generating; |
|||
|
|||
try |
|||
{ |
|||
foreach (object item in items) |
|||
{ |
|||
Control container = this.CreateContainerOverride(item); |
|||
container.TemplatedParent = null; |
|||
this.containersByItem.Add(item, container); |
|||
this.itemsByContainer.Add(container, item); |
|||
result.Add(container); |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
this.State = ItemContainerGeneratorState.Generated; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
IEnumerable<Control> IItemContainerGenerator.Remove(IEnumerable items) |
|||
{ |
|||
List<Control> result = new List<Control>(); |
|||
|
|||
foreach (var item in items) |
|||
{ |
|||
Control container = this.containersByItem[item]; |
|||
this.containersByItem.Remove(item); |
|||
this.itemsByContainer.Remove(container); |
|||
result.Add(container); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
void IItemContainerGenerator.RemoveAll() |
|||
{ |
|||
this.containersByItem.Clear(); |
|||
this.itemsByContainer.Clear(); |
|||
} |
|||
|
|||
protected virtual Control CreateContainerOverride(object item) |
|||
{ |
|||
return this.Owner.ApplyDataTemplate(item); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="TreeItemContainerGenerator.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Controls.Generators |
|||
{ |
|||
public class TreeItemContainerGenerator<T> : ItemContainerGenerator where T : TreeViewItem, new() |
|||
{ |
|||
public TreeItemContainerGenerator(ItemsControl owner) |
|||
: base(owner) |
|||
{ |
|||
} |
|||
|
|||
protected override Control CreateContainerOverride(object item) |
|||
{ |
|||
T result = item as T; |
|||
|
|||
if (result == null) |
|||
{ |
|||
TreeDataTemplate template = this.GetTreeDataTemplate(item); |
|||
|
|||
System.Diagnostics.Debug.WriteLine("{0} created item for {1}", this.GetHashCode(), item); |
|||
|
|||
result = new T |
|||
{ |
|||
Header = template.Build(item), |
|||
Items = template.ItemsSelector(item), |
|||
IsExpanded = template.IsExpanded(item), |
|||
}; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
private TreeDataTemplate GetTreeDataTemplate(object item) |
|||
{ |
|||
DataTemplate template = this.Owner.FindDataTemplate(item); |
|||
|
|||
if (template == null) |
|||
{ |
|||
template = DataTemplate.Default; |
|||
} |
|||
|
|||
TreeDataTemplate treeTemplate = template as TreeDataTemplate; |
|||
|
|||
if (treeTemplate == null) |
|||
{ |
|||
treeTemplate = new TreeDataTemplate(template.Build, x => null); |
|||
} |
|||
|
|||
return treeTemplate; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="TypedItemContainerGenerator.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Controls.Generators |
|||
{ |
|||
public class TypedItemContainerGenerator<T> : ItemContainerGenerator where T : ContentControl, new() |
|||
{ |
|||
public TypedItemContainerGenerator(ItemsControl owner) |
|||
: base(owner) |
|||
{ |
|||
} |
|||
|
|||
protected override Control CreateContainerOverride(object item) |
|||
{ |
|||
T result = item as T; |
|||
|
|||
if (result == null) |
|||
{ |
|||
result = new T(); |
|||
result.Content = this.Owner.ApplyDataTemplate(item); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue