diff --git a/nuget/build-appveyor.ps1 b/nuget/build-appveyor.ps1
index d74216def0..5d7f5f1628 100644
--- a/nuget/build-appveyor.ps1
+++ b/nuget/build-appveyor.ps1
@@ -9,11 +9,8 @@ sv version $env:APPVEYOR_BUILD_NUMBER
sv version 9999.0.$version-nightly
sv key $env:myget_key
-sv file Perspex.$version.nupkg
-
.\build-version.ps1 $version
-
sv reponame $env:APPVEYOR_REPO_NAME
sv repobranch $env:APPVEYOR_REPO_BRANCH
sv pullreq $env:APPVEYOR_PULL_REQUEST_NUMBER
@@ -26,7 +23,8 @@ if ($reponame -eq "Perspex/Perspex")
if($repobranch -eq "master")
{
echo Repo branch matched
- nuget.exe push $file $key -Source https://www.myget.org/F/perspex-nightly/api/v2/package
+ nuget.exe push Perspex.$version.nupkg $key -Source https://www.myget.org/F/perspex-nightly/api/v2/package
+ nuget.exe push Perspex.Desktop.$version.nupkg $key -Source https://www.myget.org/F/perspex-nightly/api/v2/package
}
}
diff --git a/nuget/build-version.ps1 b/nuget/build-version.ps1
index f458b30ffd..2c7e15683a 100644
--- a/nuget/build-version.ps1
+++ b/nuget/build-version.ps1
@@ -2,7 +2,8 @@ rm -Force -Recurse .\Perspex -ErrorAction SilentlyContinue
rm -Force -Recurse *.nupkg -ErrorAction SilentlyContinue
Copy-Item template Perspex -Recurse
sv lib "Perspex\lib\portable-windows8+net45"
-sv build "Perspex\build\net45"
+sv build "Perspex.Desktop\lib\net45"
+
mkdir $lib -ErrorAction SilentlyContinue
mkdir $build -ErrorAction SilentlyContinue
@@ -36,14 +37,14 @@ Copy-Item ..\src\Perspex.HtmlRenderer\bin\Release\Perspex.HtmlRenderer.dll $lib
Copy-Item ..\src\Perspex.ReactiveUI\bin\Release\Perspex.ReactiveUI.dll $lib
Copy-Item ..\src\Windows\Perspex.Direct2D1\bin\Release\Perspex.Direct2D1.dll $build
-Copy-Item ..\src\Windows\Perspex.Direct2D1\bin\Release\SharpDX.dll $build
-Copy-Item ..\src\Windows\Perspex.Direct2D1\bin\Release\SharpDX.Direct2D1.dll $build
-Copy-Item ..\src\Windows\Perspex.Direct2D1\bin\Release\SharpDX.DXGI.dll $build
Copy-Item ..\src\Windows\Perspex.Win32\bin\Release\Perspex.Win32.dll $build
Copy-Item ..\src\Gtk\Perspex.Gtk\bin\Release\Perspex.Gtk.dll $build
Copy-Item ..\src\Gtk\Perspex.Cairo\bin\Release\Perspex.Cairo.dll $build
(gc Perspex\Perspex.nuspec).replace('#VERSION#', $args[0]) | sc Perspex\Perspex.nuspec
+(gc Perspex\Perspex.Desktop.nuspec).replace('#VERSION#', $args[0]) | sc Perspex.Desktop\Perspex.Desktop.nuspec
nuget.exe pack Perspex\Perspex.nuspec
-rm -Force -Recurse .\Perspex
\ No newline at end of file
+nuget.exe pack Perspex.Desktop\Perspex.Desktop.nuspec
+rm -Force -Recurse .\Perspex
+rm -Force -Recurse .\Perspex.Desktop
\ No newline at end of file
diff --git a/nuget/template/Perspex.Desktop.nuspec b/nuget/template/Perspex.Desktop.nuspec
new file mode 100644
index 0000000000..b94e9c54f0
--- /dev/null
+++ b/nuget/template/Perspex.Desktop.nuspec
@@ -0,0 +1,29 @@
+
+
+
+ Perspex.Desktop
+ #VERSION#
+ Perspex Team
+ stevenk
+ http://opensource.org/licenses/MIT
+ https://github.com/Perspex/Perspex/
+ false
+ The Perspex UI framework
+
+ Copyright 2015
+ Perspex
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nuget/template/Perspex.nuspec b/nuget/template/Perspex.nuspec
index 45490d310e..7c55e7aaf6 100644
--- a/nuget/template/Perspex.nuspec
+++ b/nuget/template/Perspex.nuspec
@@ -3,10 +3,10 @@
Perspex
#VERSION#
- stevenk
+ Perspex Team
stevenk
http://opensource.org/licenses/MIT
- https://github.com/grokys/Perspex/
+ https://github.com/Perspex/Perspex/
false
The Perspex UI framework
Initial alpha release.
@@ -21,6 +21,7 @@
+
\ No newline at end of file
diff --git a/nuget/template/build/net45/perspex.targets b/nuget/template/build/net45/perspex.targets
deleted file mode 100644
index 70d36cf835..0000000000
--- a/nuget/template/build/net45/perspex.targets
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
- %(RecursiveDir)%(FileName)%(Extension)
- PreserveNewest
-
-
-
\ No newline at end of file
diff --git a/src/Markup/Perspex.Markup.Xaml/Binding/XamlTemplateBinding.cs b/src/Markup/Perspex.Markup.Xaml/Binding/XamlTemplateBinding.cs
index 4ccb6ff903..84794386a6 100644
--- a/src/Markup/Perspex.Markup.Xaml/Binding/XamlTemplateBinding.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Binding/XamlTemplateBinding.cs
@@ -40,7 +40,7 @@ namespace Perspex.Markup.Xaml.Binding
PerspexProperty targetProperty,
PerspexObject templatedParent)
{
- var sourceProperty = templatedParent.FindRegistered(SourcePropertyPath);
+ var sourceProperty = PerspexPropertyRegistry.Instance.FindRegistered(instance.GetType(), SourcePropertyPath);
if (sourceProperty == null)
{
diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs
index 7053eb3e95..280bcec5a6 100644
--- a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs
@@ -88,7 +88,7 @@ namespace Perspex.Markup.Xaml.Context
if (attached == null)
{
propertyName = _xamlMember.Name;
- property = perspexObject.GetRegisteredProperties()
+ property = PerspexPropertyRegistry.Instance.GetRegistered(perspexObject)
.FirstOrDefault(x => x.Name == propertyName);
}
else
@@ -98,7 +98,7 @@ namespace Perspex.Markup.Xaml.Context
propertyName = attached.DeclaringType.UnderlyingType.Name + '.' + _xamlMember.Name;
- property = perspexObject.GetRegisteredProperties()
+ property = PerspexPropertyRegistry.Instance.GetRegistered(perspexObject)
.Where(x => x.IsAttached && x.OwnerType == attached.DeclaringType.UnderlyingType)
.FirstOrDefault(x => x.Name == _xamlMember.Name);
}
diff --git a/src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs b/src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs
index f492e01111..1cdc3cc4f1 100644
--- a/src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs
@@ -46,12 +46,12 @@ namespace Perspex.Markup.Xaml.Converters
}
// First look for non-attached property on the type and then look for an attached property.
- var property = PerspexObject.GetRegisteredProperties(type)
+ var property = PerspexPropertyRegistry.Instance.GetRegistered(type)
.FirstOrDefault(x => x.Name == propertyName);
if (property == null)
{
- property = PerspexObject.GetAttachedProperties(type)
+ property = PerspexPropertyRegistry.Instance.GetAttached(type)
.FirstOrDefault(x => x.Name == propertyName);
}
diff --git a/src/Perspex.Base/Perspex.Base.csproj b/src/Perspex.Base/Perspex.Base.csproj
index b7227d831b..5b3a086f59 100644
--- a/src/Perspex.Base/Perspex.Base.csproj
+++ b/src/Perspex.Base/Perspex.Base.csproj
@@ -50,6 +50,7 @@
+
diff --git a/src/Perspex.Base/PerspexObject.cs b/src/Perspex.Base/PerspexObject.cs
index 337fbf185d..a61e04a8ac 100644
--- a/src/Perspex.Base/PerspexObject.cs
+++ b/src/Perspex.Base/PerspexObject.cs
@@ -25,18 +25,6 @@ namespace Perspex
///
public class PerspexObject : IObservablePropertyBag, INotifyPropertyChanged
{
- ///
- /// The registered properties by type.
- ///
- private static readonly Dictionary> s_registered =
- new Dictionary>();
-
- ///
- /// The registered attached properties by owner type.
- ///
- private static readonly Dictionary> s_attached =
- new Dictionary>();
-
///
/// The parent object that inherited values are inherited from.
///
@@ -70,7 +58,7 @@ namespace Perspex
new PropertyEnricher("Id", GetHashCode()),
});
- foreach (var property in GetRegisteredProperties())
+ foreach (var property in PerspexPropertyRegistry.Instance.GetRegistered(this))
{
object value = property.IsDirect ?
property.Getter(this) :
@@ -129,7 +117,7 @@ namespace Perspex
_inheritanceParent.PropertyChanged -= ParentPropertyChanged;
}
- var inherited = (from property in GetRegisteredProperties(GetType())
+ var inherited = (from property in PerspexPropertyRegistry.Instance.GetRegistered(this)
where property.Inherits
select new
{
@@ -215,92 +203,6 @@ namespace Perspex
}
}
- ///
- /// Gets all s registered on a type.
- ///
- /// The type.
- /// A collection of definitions.
- public static IEnumerable GetRegisteredProperties(Type type)
- {
- Contract.Requires(type != null);
-
- TypeInfo i = type.GetTypeInfo();
-
- while (type != null)
- {
- List list;
-
- if (s_registered.TryGetValue(type, out list))
- {
- foreach (PerspexProperty p in list)
- {
- yield return p;
- }
- }
-
- type = type.GetTypeInfo().BaseType;
- }
- }
-
- ///
- /// Gets all attached s registered by an owner.
- ///
- /// The owner type.
- /// A collection of definitions.
- public static IEnumerable GetAttachedProperties(Type ownerType)
- {
- List list;
-
- if (s_attached.TryGetValue(ownerType, out list))
- {
- return list;
- }
-
- return Enumerable.Empty();
- }
-
- ///
- /// Registers a on a type.
- ///
- /// The type.
- /// The property.
- ///
- /// You won't usually want to call this method directly, instead use the
- /// method.
- ///
- public static void Register(Type type, PerspexProperty property)
- {
- Contract.Requires(type != null);
- Contract.Requires(property != null);
-
- List list;
-
- if (!s_registered.TryGetValue(type, out list))
- {
- list = new List();
- s_registered.Add(type, list);
- }
-
- if (!list.Contains(property))
- {
- list.Add(property);
- }
-
- if (property.IsAttached)
- {
- if (!s_attached.TryGetValue(property.OwnerType, out list))
- {
- list = new List();
- s_attached.Add(property.OwnerType, list);
- }
-
- if (!list.Contains(property))
- {
- list.Add(property);
- }
- }
- }
-
public bool CheckAccess() => Dispatcher.UIThread.CheckAccess();
public void VerifyAccess() => Dispatcher.UIThread.VerifyAccess();
@@ -409,7 +311,7 @@ namespace Perspex
object result = PerspexProperty.UnsetValue;
PriorityValue value;
- if (!IsRegistered(property))
+ if (!PerspexPropertyRegistry.Instance.IsRegistered(this, property))
{
ThrowNotRegistered(property);
}
@@ -448,17 +350,6 @@ namespace Perspex
}
}
- ///
- /// Gets all properties that are registered on this object.
- ///
- ///
- /// A collection of objects.
- ///
- public IEnumerable GetRegisteredProperties()
- {
- return GetRegisteredProperties(GetType());
- }
-
///
/// Checks whether a is set on this object.
///
@@ -478,16 +369,6 @@ namespace Perspex
return false;
}
- ///
- /// Checks whether a is registered on this class.
- ///
- /// The property.
- /// True if the property is registered, otherwise false.
- public bool IsRegistered(PerspexProperty property)
- {
- return FindRegistered(property) != null;
- }
-
///
/// Sets a value.
///
@@ -519,7 +400,7 @@ namespace Perspex
PriorityValue v;
var originalValue = value;
- if (!IsRegistered(property))
+ if (!PerspexPropertyRegistry.Instance.IsRegistered(this, property))
{
ThrowNotRegistered(property);
}
@@ -620,7 +501,7 @@ namespace Perspex
{
PriorityValue v;
- if (!IsRegistered(property))
+ if (!PerspexPropertyRegistry.Instance.IsRegistered(this, property))
{
ThrowNotRegistered(property);
}
@@ -751,6 +632,12 @@ namespace Perspex
}
}
+ ///
+ bool IPropertyBag.IsRegistered(PerspexProperty property)
+ {
+ return PerspexPropertyRegistry.Instance.IsRegistered(this, property);
+ }
+
///
/// Gets all priority values set on the object.
///
@@ -936,41 +823,6 @@ namespace Perspex
}
}
- ///
- /// Given a returns a registered perspex property that is
- /// equal.
- ///
- /// The property.
- /// The registered property or null if not found.
- ///
- /// Calling AddOwner on a direct PerspexProperty creates new new PerspexProperty with
- /// an overridden getter and setter. This property is a different object but is equal
- /// according to .
- ///
- public PerspexProperty FindRegistered(PerspexProperty property)
- {
- Type type = GetType();
-
- while (type != null)
- {
- List list;
-
- if (s_registered.TryGetValue(type, out list))
- {
- var index = list.IndexOf(property);
-
- if (index != -1)
- {
- return list[index];
- }
- }
-
- type = type.GetTypeInfo().BaseType;
- }
-
- return null;
- }
-
///
/// Given a returns a registered perspex property that is
/// equal or throws if not found.
@@ -979,7 +831,7 @@ namespace Perspex
/// The registered property.
public PerspexProperty GetRegistered(PerspexProperty property)
{
- var result = FindRegistered(property);
+ var result = PerspexPropertyRegistry.Instance.FindRegistered(this, property);
if (result == null)
{
diff --git a/src/Perspex.Base/PerspexObjectExtensions.cs b/src/Perspex.Base/PerspexObjectExtensions.cs
index 6aad57bb2c..7ba3fd33d4 100644
--- a/src/Perspex.Base/PerspexObjectExtensions.cs
+++ b/src/Perspex.Base/PerspexObjectExtensions.cs
@@ -52,50 +52,6 @@ namespace Perspex
return observable.Subscribe(e => SubscribeAdapter(e, handler));
}
- ///
- /// Finds a registered property on a by name.
- ///
- /// The object.
- ///
- /// The property name. If an attached property it should be in the form
- /// "OwnerType.PropertyName".
- ///
- ///
- /// The registered property or null if no matching property found.
- ///
- public static PerspexProperty FindRegistered(this PerspexObject o, string name)
- {
- Contract.Requires(o != null);
- Contract.Requires(name != null);
-
- var parts = name.Split('.');
-
- if (parts.Length < 1 || parts.Length > 2)
- {
- throw new ArgumentException("Invalid property name.");
- }
-
- if (parts.Length == 1)
- {
- var result = o.GetRegisteredProperties()
- .FirstOrDefault(x => !x.IsAttached && x.Name == parts[0]);
-
- if (result != null)
- {
- return result;
- }
-
- // A type can .AddOwner an attached property.
- return o.GetRegisteredProperties()
- .FirstOrDefault(x => x.Name == parts[0]);
- }
- else
- {
- return o.GetRegisteredProperties()
- .FirstOrDefault(x => x.IsAttached && x.OwnerType.Name == parts[0] && x.Name == parts[1]);
- }
- }
-
///
/// Observer method for .
diff --git a/src/Perspex.Base/PerspexProperty.cs b/src/Perspex.Base/PerspexProperty.cs
index e44284b570..2dd679ce8d 100644
--- a/src/Perspex.Base/PerspexProperty.cs
+++ b/src/Perspex.Base/PerspexProperty.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Reactive.Subjects;
using System.Reflection;
using Perspex.Utilities;
@@ -28,7 +29,12 @@ namespace Perspex
private static int s_nextId = 1;
///
- /// The default values for the property, by type.
+ /// The default value provided when the property was first registered.
+ ///
+ private readonly object _defaultValue;
+
+ ///
+ /// The overridden default values for the property, by type.
///
private readonly Dictionary _defaultValues = new Dictionary();
@@ -92,7 +98,7 @@ namespace Perspex
Name = name;
PropertyType = valueType;
OwnerType = ownerType;
- _defaultValues.Add(ownerType, defaultValue);
+ _defaultValue = defaultValue;
Inherits = inherits;
DefaultBindingMode = defaultBindingMode;
IsAttached = isAttached;
@@ -143,14 +149,57 @@ namespace Perspex
/// Initializes a new instance of the class.
///
/// The direct property to copy.
+ /// The new owner type.
+ protected PerspexProperty(PerspexProperty source, Type ownerType)
+ {
+ Contract.Requires(source != null);
+ Contract.Requires(ownerType != null);
+
+ if (source.IsDirect)
+ {
+ throw new InvalidOperationException(
+ "This method cannot be called on direct PerspexProperties.");
+ }
+
+ //Name = name;
+ //PropertyType = valueType;
+ //OwnerType = ownerType;
+ //_defaultValues.Add(ownerType, defaultValue);
+ //Inherits = inherits;
+ //DefaultBindingMode = defaultBindingMode;
+ //IsAttached = isAttached;
+ //Notifying = notifying;
+ //_id = s_nextId++;
+
+
+ Name = source.Name;
+ PropertyType = source.PropertyType;
+ OwnerType = ownerType;
+ _defaultValue = source._defaultValue;
+ _defaultValues = source._defaultValues;
+ Inherits = source.Inherits;
+ DefaultBindingMode = source.DefaultBindingMode;
+ IsAttached = false;
+ Notifying = Notifying;
+ _validation = source._validation;
+ _id = source._id;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The direct property to copy.
+ /// The new owner type.
/// A new getter.
/// A new setter.
protected PerspexProperty(
PerspexProperty source,
+ Type ownerType,
Func getter,
Action setter)
{
Contract.Requires(source != null);
+ Contract.Requires(ownerType != null);
Contract.Requires(getter != null);
if (!source.IsDirect)
@@ -161,7 +210,7 @@ namespace Perspex
Name = source.Name;
PropertyType = source.PropertyType;
- OwnerType = source.OwnerType;
+ OwnerType = ownerType;
Getter = getter;
Setter = setter;
IsDirect = true;
@@ -367,7 +416,7 @@ namespace Perspex
notifying,
false);
- PerspexObject.Register(typeof(TOwner), result);
+ PerspexPropertyRegistry.Instance.Register(typeof(TOwner), result);
return result;
}
@@ -395,7 +444,7 @@ namespace Perspex
Cast(getter),
Cast(setter));
- PerspexObject.Register(typeof(TOwner), result);
+ PerspexPropertyRegistry.Instance.Register(typeof(TOwner), result);
return result;
}
@@ -431,7 +480,7 @@ namespace Perspex
null,
true);
- PerspexObject.Register(typeof(THost), result);
+ PerspexPropertyRegistry.Instance.Register(typeof(THost), result);
return result;
}
@@ -468,7 +517,7 @@ namespace Perspex
null,
true);
- PerspexObject.Register(typeof(THost), result);
+ PerspexPropertyRegistry.Instance.Register(typeof(THost), result);
return result;
}
@@ -529,7 +578,7 @@ namespace Perspex
type = type.GetTypeInfo().BaseType;
}
- return _defaultValues[OwnerType];
+ return _defaultValue;
}
///
diff --git a/src/Perspex.Base/PerspexPropertyRegistry.cs b/src/Perspex.Base/PerspexPropertyRegistry.cs
new file mode 100644
index 0000000000..2c388131fa
--- /dev/null
+++ b/src/Perspex.Base/PerspexPropertyRegistry.cs
@@ -0,0 +1,255 @@
+// 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.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Perspex
+{
+ ///
+ /// Tracks registered instances.
+ ///
+ public class PerspexPropertyRegistry
+ {
+ ///
+ /// The registered properties by type.
+ ///
+ private readonly Dictionary> _registered =
+ new Dictionary>();
+
+ ///
+ /// The registered attached properties by owner type.
+ ///
+ private readonly Dictionary> _attached =
+ new Dictionary>();
+
+ ///
+ /// Gets the instance
+ ///
+ public static PerspexPropertyRegistry Instance { get; }
+ = new PerspexPropertyRegistry();
+
+ ///
+ /// Gets all attached s registered by an owner.
+ ///
+ /// The owner type.
+ /// A collection of definitions.
+ public IEnumerable GetAttached(Type ownerType)
+ {
+ List list;
+
+ if (_attached.TryGetValue(ownerType, out list))
+ {
+ return list;
+ }
+
+ return Enumerable.Empty();
+ }
+
+ ///
+ /// Gets all s registered on a type.
+ ///
+ /// The type.
+ /// A collection of definitions.
+ public IEnumerable GetRegistered(Type type)
+ {
+ Contract.Requires(type != null);
+
+ var i = type.GetTypeInfo();
+
+ while (type != null)
+ {
+ List list;
+
+ if (_registered.TryGetValue(type, out list))
+ {
+ foreach (PerspexProperty p in list)
+ {
+ yield return p;
+ }
+ }
+
+ type = type.GetTypeInfo().BaseType;
+ }
+ }
+
+ ///
+ /// Gets all s registered on a object.
+ ///
+ /// The object.
+ /// A collection of definitions.
+ public IEnumerable GetRegistered(PerspexObject o)
+ {
+ Contract.Requires(o != null);
+
+ return GetRegistered(o.GetType());
+ }
+
+ ///
+ /// Finds registered on a type.
+ ///
+ /// The type.
+ /// The property.
+ /// The registered property or null if not found.
+ ///
+ /// Calling AddOwner on a PerspexProperty creates a new PerspexProperty that is a
+ /// different object but is equal according to .
+ ///
+ public PerspexProperty FindRegistered(Type type, PerspexProperty property)
+ {
+ while (type != null)
+ {
+ List list;
+
+ if (_registered.TryGetValue(type, out list))
+ {
+ var index = list.IndexOf(property);
+
+ if (index != -1)
+ {
+ return list[index];
+ }
+ }
+
+ type = type.GetTypeInfo().BaseType;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Finds registered on an object.
+ ///
+ /// The object.
+ /// The property.
+ /// The registered property or null if not found.
+ ///
+ /// Calling AddOwner on a PerspexProperty creates a new PerspexProperty that is a
+ /// different object but is equal according to .
+ ///
+ public PerspexProperty FindRegistered(object o, PerspexProperty property)
+ {
+ return FindRegistered(o.GetType(), property);
+ }
+
+ ///
+ /// Finds a registered property on a type by name.
+ ///
+ /// The type.
+ ///
+ /// The property name. If an attached property it should be in the form
+ /// "OwnerType.PropertyName".
+ ///
+ ///
+ /// The registered property or null if no matching property found.
+ ///
+ public PerspexProperty FindRegistered(Type type, string name)
+ {
+ Contract.Requires(type != null);
+ Contract.Requires(name != null);
+
+ var parts = name.Split('.');
+
+ if (parts.Length < 1 || parts.Length > 2)
+ {
+ throw new ArgumentException("Invalid property name.");
+ }
+
+ string propertyName;
+ var results = GetRegistered(type);
+
+ if (parts.Length == 1)
+ {
+ propertyName = parts[0];
+ }
+ else
+ {
+ var types = GetImplementedTypes(type);
+
+ if (!types.Contains(parts[0]))
+ {
+ results = results.Where(x => x.OwnerType.Name == parts[0]);
+ }
+
+ propertyName = parts[1];
+ }
+
+ return results.FirstOrDefault(x => x.Name == propertyName);
+ }
+
+ private IEnumerable GetImplementedTypes(Type type)
+ {
+ while (type != null)
+ {
+ yield return type.Name;
+ type = type.GetTypeInfo().BaseType;
+ }
+ }
+
+ ///
+ /// Checks whether a is registered on a type.
+ ///
+ /// The type.
+ /// The property.
+ /// True if the property is registered, otherwise false.
+ public bool IsRegistered(Type type, PerspexProperty property)
+ {
+ return FindRegistered(type, property) != null;
+ }
+
+ ///
+ /// Checks whether a is registered on a object.
+ ///
+ /// The object.
+ /// The property.
+ /// True if the property is registered, otherwise false.
+ public bool IsRegistered(object o, PerspexProperty property)
+ {
+ return IsRegistered(o.GetType(), property);
+ }
+
+ ///
+ /// Registers a on a type.
+ ///
+ /// The type.
+ /// The property.
+ ///
+ /// You won't usually want to call this method directly, instead use the
+ /// method.
+ ///
+ public void Register(Type type, PerspexProperty property)
+ {
+ Contract.Requires(type != null);
+ Contract.Requires(property != null);
+
+ List list;
+
+ if (!_registered.TryGetValue(type, out list))
+ {
+ list = new List();
+ _registered.Add(type, list);
+ }
+
+ if (!list.Contains(property))
+ {
+ list.Add(property);
+ }
+
+ if (property.IsAttached)
+ {
+ if (!_attached.TryGetValue(property.OwnerType, out list))
+ {
+ list = new List();
+ _attached.Add(property.OwnerType, list);
+ }
+
+ if (!list.Contains(property))
+ {
+ list.Add(property);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Perspex.Base/PerspexProperty`1.cs b/src/Perspex.Base/PerspexProperty`1.cs
index 73ac84e102..6d97833f0a 100644
--- a/src/Perspex.Base/PerspexProperty`1.cs
+++ b/src/Perspex.Base/PerspexProperty`1.cs
@@ -66,17 +66,29 @@ namespace Perspex
Setter = setter;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The property to copy.
+ /// The new owner type.
+ private PerspexProperty(PerspexProperty source, Type ownerType)
+ : base(source, ownerType)
+ {
+ }
+
///
/// Initializes a new instance of the class.
///
/// The direct property to copy.
+ /// The new owner type.
/// A new getter.
/// A new setter.
private PerspexProperty(
PerspexProperty source,
+ Type ownerType,
Func getter,
Action setter)
- : base(source, CastParamReturn(getter), CastParams(setter))
+ : base(source, ownerType, CastParamReturn(getter), CastParams(setter))
{
Getter = getter;
Setter = setter;
@@ -105,8 +117,9 @@ namespace Perspex
"You must provide a new getter and setter when calling AddOwner on a direct PerspexProperty.");
}
- PerspexObject.Register(typeof(TOwner), this);
- return this;
+ var result = new PerspexProperty(this, typeof(TOwner));
+ PerspexPropertyRegistry.Instance.Register(typeof(TOwner), result);
+ return result;
}
///
@@ -119,8 +132,19 @@ namespace Perspex
Action setter = null)
where TOwner : PerspexObject
{
- var result = new PerspexProperty(this, CastReturn(getter), CastParam1(setter));
- PerspexObject.Register(typeof(TOwner), result);
+ if (!IsDirect)
+ {
+ throw new InvalidOperationException(
+ "This overload of AddOwner is for direct PerspexProperties.");
+ }
+
+ var result = new PerspexProperty(
+ this,
+ typeof(TOwner),
+ CastReturn(getter),
+ CastParam1(setter));
+
+ PerspexPropertyRegistry.Instance.Register(typeof(TOwner), result);
return result;
}
diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs
index e41be6ccc3..62150c76b9 100644
--- a/src/Perspex.Controls/Control.cs
+++ b/src/Perspex.Controls/Control.cs
@@ -406,7 +406,11 @@ namespace Perspex.Controls
base.OnAttachedToVisualTree(root);
IStyler styler = PerspexLocator.Current.GetService();
- styler.ApplyStyles(this);
+
+ if (styler != null)
+ {
+ styler.ApplyStyles(this);
+ }
}
///
diff --git a/src/Perspex.Controls/DropDown.cs b/src/Perspex.Controls/DropDown.cs
index eff7d2c4fe..23aba16009 100644
--- a/src/Perspex.Controls/DropDown.cs
+++ b/src/Perspex.Controls/DropDown.cs
@@ -80,7 +80,7 @@ namespace Perspex.Controls
protected override IItemContainerGenerator CreateItemContainerGenerator()
{
- return new ItemContainerGenerator(this);
+ return new ItemContainerGenerator(this, ListBoxItem.ContentProperty);
}
protected override void OnKeyDown(KeyEventArgs e)
diff --git a/src/Perspex.Controls/Generators/IItemContainerGenerator.cs b/src/Perspex.Controls/Generators/IItemContainerGenerator.cs
index 2009131bc5..7189d7a0c9 100644
--- a/src/Perspex.Controls/Generators/IItemContainerGenerator.cs
+++ b/src/Perspex.Controls/Generators/IItemContainerGenerator.cs
@@ -32,26 +32,37 @@ namespace Perspex.Controls.Generators
/// The items.
/// An optional member selector.
/// The created controls.
- IList CreateContainers(
+ IEnumerable Materialize(
int startingIndex,
IEnumerable items,
IMemberSelector selector);
///
- /// Removes a set of created containers from the index and returns the removed controls.
+ /// Removes a set of created containers.
///
///
/// The index of the first item of the data in the containing collection.
///
- /// The items.
- /// The removed controls.
- IList RemoveContainers(int startingIndex, IEnumerable items);
+ /// The the number of items to remove.
+ /// The removed containers.
+ IEnumerable Dematerialize(int startingIndex, int count);
+
+ ///
+ /// Removes a set of created containers and updates the index of later containers to fill
+ /// the gap.
+ ///
+ ///
+ /// The index of the first item of the data in the containing collection.
+ ///
+ /// The the number of items to remove.
+ /// The removed containers.
+ IEnumerable RemoveRange(int startingIndex, int count);
///
- /// Clears the created containers from the index and returns the removed controls.
+ /// Clears all created containers and returns the removed controls.
///
/// The removed controls.
- IList ClearContainers();
+ IEnumerable Clear();
///
/// Gets the container control representing the item with the specified index.
diff --git a/src/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs b/src/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs
index 0555fd436f..37f097618b 100644
--- a/src/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs
+++ b/src/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs
@@ -11,23 +11,23 @@ namespace Perspex.Controls.Generators
public interface ITreeItemContainerGenerator : IItemContainerGenerator
{
///
- /// Gets all of the generated container controls.
+ /// Gets the item container for the root of the tree, or null if this generator is itself
+ /// the root of the tree.
///
- /// The containers.
- IEnumerable GetAllContainers();
+ ITreeItemContainerGenerator RootGenerator { get; }
///
- /// Gets the item that is contained by the specified container.
+ /// Gets the item container for the specified item, anywhere in the tree.
///
- /// The container.
- /// The item.
- object ItemFromContainer(IControl container);
+ /// The item.
+ /// The container, or null if not found.
+ IControl TreeContainerFromItem(object item);
///
- /// Gets the container for the specified item
+ /// Gets the item for the specified item container, anywhere in the tree.
///
- /// The item.
- /// The container.
- IControl ContainerFromItem(object item);
+ /// The container.
+ /// The item, or null if not found.
+ object TreeItemFromContainer(IControl container);
}
}
\ No newline at end of file
diff --git a/src/Perspex.Controls/Generators/ItemContainerGenerator.cs b/src/Perspex.Controls/Generators/ItemContainerGenerator.cs
index 9e8183c322..b8b57ddd59 100644
--- a/src/Perspex.Controls/Generators/ItemContainerGenerator.cs
+++ b/src/Perspex.Controls/Generators/ItemContainerGenerator.cs
@@ -15,7 +15,7 @@ namespace Perspex.Controls.Generators
///
public class ItemContainerGenerator : IItemContainerGenerator
{
- private Dictionary _containers = new Dictionary();
+ private List _containers = new List();
private readonly Subject _containersInitialized = new Subject();
@@ -25,17 +25,15 @@ namespace Perspex.Controls.Generators
/// The owner control.
public ItemContainerGenerator(IControl owner)
{
+ Contract.Requires(owner != null);
+
Owner = owner;
}
- ///
- /// Gets the currently realized containers.
- ///
- public IEnumerable Containers => _containers.Values;
+ ///
+ public IEnumerable Containers => _containers;
- ///
- /// Signalled whenever new containers are initialized.
- ///
+ ///
public IObservable ContainersInitialized => _containersInitialized;
///
@@ -43,16 +41,8 @@ namespace Perspex.Controls.Generators
///
public IControl Owner { get; }
- ///
- /// Creates container controls for a collection of items.
- ///
- ///
- /// The index of the first item of the data in the containing collection.
- ///
- /// The items.
- /// An optional member selector.
- /// The created container controls.
- public IList CreateContainers(
+ ///
+ public IEnumerable Materialize(
int startingIndex,
IEnumerable items,
IMemberSelector selector)
@@ -75,72 +65,54 @@ namespace Perspex.Controls.Generators
return result.Where(x => x != null).ToList();
}
- ///
- /// Removes a set of created containers from the index and returns the removed controls.
- ///
- ///
- /// The index of the first item of the data in the containing collection.
- ///
- /// The items.
- /// The removed controls.
- public IList RemoveContainers(int startingIndex, IEnumerable items)
+ ///
+ public virtual IEnumerable Dematerialize(int startingIndex, int count)
{
var result = new List();
- var count = items.Cast
/// The type of the container.
- public class TreeItemContainerGenerator : ITreeItemContainerGenerator where T : TreeViewItem, new()
+ public class TreeItemContainerGenerator : ItemContainerGenerator, ITreeItemContainerGenerator
+ where T : class, IControl, new()
{
- private Dictionary