diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 78b9cff039..acff8cc117 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,18 +1,18 @@
## What does the pull request do?
+
-Give a bit of background on the PR here, together with links to with related issues etc.
## What is the current behavior?
+
-If the PR is a fix, describe the current incorrect behavior, otherwise delete this section.
## What is the updated/expected behavior with this PR?
+
-Describe how to test the PR.
## How was the solution implemented (if it's not obvious)?
+
-Include any information that might be of use to a reviewer here.
## Checklist
@@ -21,12 +21,11 @@ Include any information that might be of use to a reviewer here.
- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Avaloniaui.net with user documentation
## Breaking changes
+
-List any breaking changes here. When the PR is merged please add an entry to https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes
## Fixed issues
-
-If the pull request fixes issue(s) list them like this:
-
+
diff --git a/Avalonia.sln b/Avalonia.sln
index 2f7560049c..d6472503fe 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -196,9 +196,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "nukebuild\_build.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Animation.UnitTests", "tests\Avalonia.Animation.UnitTests\Avalonia.Animation.UnitTests.csproj", "{AF227847-E65C-4BE9-BCE9-B551357788E0}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.X11", "src\Avalonia.X11\Avalonia.X11.csproj", "{41B02319-965D-4945-8005-C1A3D1224165}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.X11", "src\Avalonia.X11\Avalonia.X11.csproj", "{41B02319-965D-4945-8005-C1A3D1224165}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlatformSanityChecks", "samples\PlatformSanityChecks\PlatformSanityChecks.csproj", "{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlatformSanityChecks", "samples\PlatformSanityChecks\PlatformSanityChecks.csproj", "{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI.UnitTests", "tests\Avalonia.ReactiveUI.UnitTests\Avalonia.ReactiveUI.UnitTests.csproj", "{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
@@ -1819,6 +1821,30 @@ Global
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhone.Build.0 = Release|Any CPU
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhone.Build.0 = Release|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1875,6 +1901,7 @@ Global
{AF227847-E65C-4BE9-BCE9-B551357788E0} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/nukebuild/BuildParameters.cs b/nukebuild/BuildParameters.cs
index afd1950859..65ba5e9756 100644
--- a/nukebuild/BuildParameters.cs
+++ b/nukebuild/BuildParameters.cs
@@ -109,7 +109,7 @@ public partial class Build
if (!IsNuGetRelease)
{
// Use AssemblyVersion with Build as version
- Version += "-build" + Environment.GetEnvironmentVariable("BUILD_BUILDID") + "-beta";
+ Version += "-cibuild" + int.Parse(Environment.GetEnvironmentVariable("BUILD_BUILDID")).ToString("0000000") + "-beta";
}
PublishTestResults = true;
diff --git a/scripts/ReplaceNugetCache.ps1 b/scripts/ReplaceNugetCache.ps1
index 6de50f978d..70f5eaa40b 100644
--- a/scripts/ReplaceNugetCache.ps1
+++ b/scripts/ReplaceNugetCache.ps1
@@ -1,6 +1,5 @@
-copy ..\samples\ControlCatalog.Desktop\bin\Debug\net461\Avalonia**.dll ~\.nuget\packages\avalonia\$args\lib\net461\
copy ..\samples\ControlCatalog.NetCore\bin\Debug\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia\$args\lib\netcoreapp2.0\
copy ..\samples\ControlCatalog.NetCore\bin\Debug\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia\$args\lib\netstandard2.0\
-copy ..\samples\ControlCatalog.NetCore\bin\Debug\netcoreapp2.0\Avalonia.Gtk3.dll ~\.nuget\packages\avalonia.gtk3\$args\lib\netstandard2.0\
copy ..\samples\ControlCatalog.NetCore\bin\Debug\netcoreapp2.0\Avalonia.Win32.dll ~\.nuget\packages\avalonia.win32\$args\lib\netstandard2.0\
copy ..\samples\ControlCatalog.NetCore\bin\Debug\netcoreapp2.0\Avalonia.Skia.dll ~\.nuget\packages\avalonia.skia\$args\lib\netstandard2.0\
+copy ..\samples\ControlCatalog.NetCore\bin\Debug\netcoreapp2.0\Avalonia.Skia.dll ~\.nuget\packages\avalonia.direct2d1\$args\lib\netstandard2.0\
diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index 90b6aca505..7601b64ce9 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -36,32 +36,7 @@ namespace Avalonia
public AvaloniaObject()
{
VerifyAccess();
-
- void Notify(AvaloniaProperty property)
- {
- object value = property.IsDirect ?
- ((IDirectPropertyAccessor)property).GetValue(this) :
- ((IStyledPropertyAccessor)property).GetDefaultValue(GetType());
-
- var e = new AvaloniaPropertyChangedEventArgs(
- this,
- property,
- AvaloniaProperty.UnsetValue,
- value,
- BindingPriority.Unset);
-
- property.NotifyInitialized(e);
- }
-
- foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegistered(this))
- {
- Notify(property);
- }
-
- foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegisteredAttached(this.GetType()))
- {
- Notify(property);
- }
+ AvaloniaPropertyRegistry.Instance.NotifyInitialized(this);
}
///
@@ -645,7 +620,7 @@ namespace Avalonia
///
/// The property.
/// The default value.
- internal object GetDefaultValue(AvaloniaProperty property)
+ private object GetDefaultValue(AvaloniaProperty property)
{
if (property.Inherits && InheritanceParent is AvaloniaObject aobj)
return aobj.GetValue(property);
diff --git a/src/Avalonia.Base/AvaloniaProperty.cs b/src/Avalonia.Base/AvaloniaProperty.cs
index 4b0116a536..953132116c 100644
--- a/src/Avalonia.Base/AvaloniaProperty.cs
+++ b/src/Avalonia.Base/AvaloniaProperty.cs
@@ -21,7 +21,7 @@ namespace Avalonia
///
public static readonly object UnsetValue = new Unset();
- private static int s_nextId = 1;
+ private static int s_nextId;
private readonly Subject _initialized;
private readonly Subject _changed;
private readonly PropertyMetadata _defaultMetadata;
diff --git a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs
index e29e7339ae..037e0dd72e 100644
--- a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs
+++ b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
+using Avalonia.Data;
namespace Avalonia
{
@@ -13,6 +14,8 @@ namespace Avalonia
///
public class AvaloniaPropertyRegistry
{
+ private readonly Dictionary _properties =
+ new Dictionary();
private readonly Dictionary> _registered =
new Dictionary>();
private readonly Dictionary> _attached =
@@ -21,6 +24,8 @@ namespace Avalonia
new Dictionary>();
private readonly Dictionary> _attachedCache =
new Dictionary>();
+ private readonly Dictionary>> _initializedCache =
+ new Dictionary>>();
///
/// Gets the instance
@@ -28,6 +33,11 @@ namespace Avalonia
public static AvaloniaPropertyRegistry Instance { get; }
= new AvaloniaPropertyRegistry();
+ ///
+ /// Gets a list of all registered properties.
+ ///
+ internal IReadOnlyCollection Properties => _properties.Values;
+
///
/// Gets all non-attached s registered on a type.
///
@@ -148,6 +158,16 @@ namespace Avalonia
return FindRegistered(o.GetType(), name);
}
+ ///
+ /// Finds a registered property by Id.
+ ///
+ /// The property Id.
+ /// The registered property or null if no matching property found.
+ internal AvaloniaProperty FindRegistered(int id)
+ {
+ return id < _properties.Count ? _properties[id] : null;
+ }
+
///
/// Checks whether a is registered on a type.
///
@@ -202,8 +222,14 @@ namespace Avalonia
{
inner.Add(property.Id, property);
}
-
+
+ if (!_properties.ContainsKey(property.Id))
+ {
+ _properties.Add(property.Id, property);
+ }
+
_registeredCache.Clear();
+ _initializedCache.Clear();
}
///
@@ -237,8 +263,59 @@ namespace Avalonia
{
inner.Add(property.Id, property);
}
-
+
_attachedCache.Clear();
+ _initializedCache.Clear();
+ }
+
+ internal void NotifyInitialized(AvaloniaObject o)
+ {
+ Contract.Requires(o != null);
+
+ var type = o.GetType();
+
+ void Notify(AvaloniaProperty property, object value)
+ {
+ var e = new AvaloniaPropertyChangedEventArgs(
+ o,
+ property,
+ AvaloniaProperty.UnsetValue,
+ value,
+ BindingPriority.Unset);
+
+ property.NotifyInitialized(e);
+ }
+
+ if (!_initializedCache.TryGetValue(type, out var items))
+ {
+ var build = new Dictionary();
+
+ foreach (var property in GetRegistered(type))
+ {
+ var value = !property.IsDirect ?
+ ((IStyledPropertyAccessor)property).GetDefaultValue(type) :
+ null;
+ build.Add(property, value);
+ }
+
+ foreach (var property in GetRegisteredAttached(type))
+ {
+ if (!build.ContainsKey(property))
+ {
+ var value = ((IStyledPropertyAccessor)property).GetDefaultValue(type);
+ build.Add(property, value);
+ }
+ }
+
+ items = build.ToList();
+ _initializedCache.Add(type, items);
+ }
+
+ foreach (var i in items)
+ {
+ var value = i.Key.IsDirect ? o.GetValue(i.Key) : i.Value;
+ Notify(i.Key, value);
+ }
}
}
}
diff --git a/src/Avalonia.Base/Data/Core/BindingExpression.cs b/src/Avalonia.Base/Data/Core/BindingExpression.cs
index c4ffa839e0..f1717bde3b 100644
--- a/src/Avalonia.Base/Data/Core/BindingExpression.cs
+++ b/src/Avalonia.Base/Data/Core/BindingExpression.cs
@@ -177,7 +177,7 @@ namespace Avalonia.Data.Core
protected override void Subscribed(IObserver
public class ObservableStreamPlugin : IStreamPlugin
{
+ static MethodInfo observableSelect;
+
///
/// Checks whether this plugin handles the specified value.
///
/// A weak reference to the value.
/// True if the plugin can handle the value; otherwise false.
- public virtual bool Match(WeakReference reference) => reference.Target is IObservable