Browse Source

Added start of ItemsControl.

pull/4/head
Steven Kirk 12 years ago
parent
commit
435f4df665
  1. 21
      Perspex/Application.cs
  2. 35
      Perspex/Controls/ContentPresenter.cs
  3. 43
      Perspex/Controls/Control.cs
  4. 6
      Perspex/Controls/DataTemplate.cs
  5. 99
      Perspex/Controls/ItemsControl.cs
  6. 20
      Perspex/Controls/ItemsPanelTemplate.cs
  7. 2
      Perspex/Controls/Panel.cs
  8. 2
      Perspex/Perspex.csproj
  9. 19
      Perspex/PerspexList.cs
  10. 35
      TestApplication/Program.cs

21
Perspex/Application.cs

@ -6,12 +6,15 @@
namespace Perspex
{
using Perspex.Controls;
using Perspex.Input;
using Perspex.Styling;
using Splat;
public class Application
{
private DataTemplates dataTemplates;
private Styles styles;
public Application()
@ -27,6 +30,24 @@ namespace Perspex
private set;
}
public DataTemplates DataTemplates
{
get
{
if (this.dataTemplates == null)
{
this.dataTemplates = new DataTemplates();
}
return this.dataTemplates;
}
set
{
this.dataTemplates = value;
}
}
public IFocusManager FocusManager
{
get;

35
Perspex/Controls/ContentPresenter.cs

@ -46,6 +46,11 @@ namespace Perspex.Controls
set { this.SetValue(ContentProperty, value); }
}
IEnumerable<IVisual> IVisual.ExistingVisualChildren
{
get { return Enumerable.Repeat(this.visualChild, this.visualChild != null ? 1 : 0); }
}
IEnumerable<IVisual> IVisual.VisualChildren
{
get
@ -154,35 +159,5 @@ namespace Perspex.Controls
return new Size();
}
private DataTemplate FindDataTemplate(object content)
{
ILogical node = this;
while (node != null)
{
Control control = node as Control;
if (control != null)
{
foreach (DataTemplate dt in control.DataTemplates.Reverse())
{
if (dt.Match(content))
{
return dt;
}
}
}
node = node.LogicalParent;
if (node == null && control != null)
{
node = control.TemplatedParent as ILogical;
}
}
return null;
}
}
}

43
Perspex/Controls/Control.cs

@ -208,5 +208,48 @@ namespace Perspex.Controls
}
});
}
protected DataTemplate FindDataTemplate(object content)
{
ILogical node = this;
while (node != null)
{
Control control = node as Control;
if (control != null)
{
foreach (DataTemplate dt in control.DataTemplates.Reverse())
{
if (dt.Match(content))
{
return dt;
}
}
}
node = node.LogicalParent;
if (node == null && control != null)
{
node = control.TemplatedParent as ILogical;
}
}
foreach (DataTemplate dt in Application.Current.DataTemplates.Reverse())
{
if (dt.Match(content))
{
return dt;
}
}
return null;
}
protected DataTemplate GetDataTemplate(object content)
{
return this.FindDataTemplate(content) ?? DataTemplate.Default;
}
}
}

6
Perspex/Controls/DataTemplate.cs

@ -11,6 +11,9 @@ namespace Perspex.Controls
public class DataTemplate
{
public static readonly DataTemplate Default =
new DataTemplate(typeof(object), o => new TextBox { Text = o.ToString() });
public DataTemplate(Type type, Func<object, IVisual> build)
: this(o => type.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo()), build)
{
@ -18,6 +21,9 @@ namespace Perspex.Controls
public DataTemplate(Func<object, bool> match, Func<object, IVisual> build)
{
Contract.Requires<ArgumentNullException>(match != null);
Contract.Requires<ArgumentNullException>(build != null);
this.Match = match;
this.Build = build;
}

99
Perspex/Controls/ItemsControl.cs

@ -0,0 +1,99 @@
// -----------------------------------------------------------------------
// <copyright file="ItemsControl.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Perspex.Layout;
public class ItemsControl : Control, IVisual
{
private static readonly ItemsPanelTemplate defaultPanel =
new ItemsPanelTemplate(() => new StackPanel { Orientation = Orientation.Vertical });
public static readonly PerspexProperty<IEnumerable> ItemsProperty =
PerspexProperty.Register<ItemsControl, IEnumerable>("Items");
public static readonly PerspexProperty<ItemsPanelTemplate> ItemsPanelProperty =
PerspexProperty.Register<ItemsControl, ItemsPanelTemplate>("ItemsPanel", defaultValue: defaultPanel);
private Panel panel;
public ItemsControl()
{
this.GetObservable(ItemsProperty).Subscribe(this.ItemsChanged);
}
public IEnumerable Items
{
get { return this.GetValue(ItemsProperty); }
set { this.SetValue(ItemsProperty, value); }
}
public ItemsPanelTemplate ItemsPanel
{
get { return this.GetValue(ItemsPanelProperty); }
set { this.SetValue(ItemsPanelProperty, value); }
}
IEnumerable<IVisual> IVisual.ExistingVisualChildren
{
get { return Enumerable.Repeat(this.panel, this.panel != null ? 1 : 0); }
}
IEnumerable<IVisual> IVisual.VisualChildren
{
get { return Enumerable.Repeat(this.GetPanel(), 1); }
}
protected override Size MeasureOverride(Size availableSize)
{
Panel panel = this.GetPanel();
panel.Measure(availableSize);
return panel.DesiredSize.Value;
}
protected override Size ArrangeOverride(Size finalSize)
{
this.GetPanel().Arrange(new Rect(finalSize));
return finalSize;
}
private IEnumerable<Control> CreateItems(IEnumerable items)
{
if (items != null)
{
return items
.Cast<object>()
.Select(x => this.GetDataTemplate(x).Build(x))
.OfType<Control>();
}
else
{
return Enumerable.Empty<Control>();
}
}
private Panel GetPanel()
{
if (this.panel == null)
{
this.panel = this.ItemsPanel.Build();
this.panel.Children = new PerspexList<Control>(this.CreateItems(this.Items));
}
return this.panel;
}
private void ItemsChanged(IEnumerable items)
{
this.GetPanel().Children = new PerspexList<Control>(this.CreateItems(items));
}
}
}

20
Perspex/Controls/ItemsPanelTemplate.cs

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Perspex.Controls
{
public class ItemsPanelTemplate
{
public ItemsPanelTemplate(Func<Panel> build)
{
Contract.Requires<ArgumentNullException>(build != null);
this.Build = build;
}
public Func<Panel> Build { get; private set; }
}
}

2
Perspex/Controls/Panel.cs

@ -53,7 +53,7 @@ namespace Perspex.Controls
IEnumerable<IVisual> IVisual.VisualChildren
{
get { return this.children; }
get { return this.children ?? Enumerable.Empty<IVisual>(); }
}
}
}

2
Perspex/Perspex.csproj

@ -70,6 +70,8 @@
<ItemGroup>
<Compile Include="Application.cs" />
<Compile Include="BindingExtensions.cs" />
<Compile Include="Controls\ItemsPanelTemplate.cs" />
<Compile Include="Controls\ItemsControl.cs" />
<Compile Include="Controls\DataTemplate.cs" />
<Compile Include="Controls\DataTemplates.cs" />
<Compile Include="Controls\CheckBox.cs" />

19
Perspex/PerspexList.cs

@ -16,10 +16,13 @@ namespace Perspex
{
public PerspexList()
{
this.Changed = Observable.FromEvent<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
handler => (sender, e) => handler(e),
handler => this.CollectionChanged += handler,
handler => this.CollectionChanged -= handler);
this.Initialize();
}
public PerspexList(IEnumerable<T> items)
: base(items)
{
this.Initialize();
}
public IObservable<NotifyCollectionChangedEventArgs> Changed
@ -35,5 +38,13 @@ namespace Perspex
this.Add(item);
}
}
private void Initialize()
{
this.Changed = Observable.FromEvent<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
handler => (sender, e) => handler(e),
handler => this.CollectionChanged += handler,
handler => this.CollectionChanged -= handler);
}
}
}

35
TestApplication/Program.cs

@ -36,6 +36,12 @@ namespace TestApplication
}
}
class Item
{
public string Name { get; set; }
public string Value { get; set; }
}
class Program
{
static void Main(string[] args)
@ -76,23 +82,38 @@ namespace TestApplication
Source = new Bitmap("github_icon.png"),
Width = 200,
},
new ContentControl
new ItemsControl
{
DataTemplates = new DataTemplates
{
new DataTemplate<string>(o => new Border
new DataTemplate<Item>(o => new Border
{
Background = Brushes.Red,
BorderBrush = Brushes.Black,
BorderThickness = 2,
Content = new TextBlock
BorderThickness = 1,
Content = new StackPanel
{
Text = o,
Orientation = Orientation.Vertical,
Children = new PerspexList<Control>
{
new TextBlock
{
Text = o.Name,
},
new TextBlock
{
Text = o.Value,
}
},
}
}),
},
Content = "Data Template",
},
Items = new[]
{
new Item { Name = "Foo", Value = "Bar" },
new Item { Name = "Buzz", Value = "Aldrin" },
},
}
}
}
};

Loading…
Cancel
Save