diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 76abcf6912..44d5c239ef 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -4,11 +4,16 @@
Avalonia
0.8.999
Copyright 2019 © The AvaloniaUI Project
- https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md
- https://github.com/AvaloniaUI/Avalonia/
+ https://avaloniaui.net
https://github.com/AvaloniaUI/Avalonia/
true
CS1591
latest
+ MIT
+ https://avatars2.githubusercontent.com/u/14075148?s=200
+ Avalonia is a WPF/UWP-inspired cross-platform XAML-based UI framework providing a flexible styling system and supporting a wide range of Operating Systems such as Windows (.NET Framework, .NET Core), Linux (via Xorg), MacOS and with experimental support for Android and iOS.
+ avalonia;avaloniaui;mvvm;rx;reactive extensions;android;ios;mac;forms;wpf;net;netstandard;net461;uwp;xamarin
+ https://github.com/AvaloniaUI/Avalonia/releases
+ git
diff --git a/scripts/ReplaceNugetCache.sh b/scripts/ReplaceNugetCache.sh
index 4cc11edd60..e1c0487d60 100755
--- a/scripts/ReplaceNugetCache.sh
+++ b/scripts/ReplaceNugetCache.sh
@@ -2,7 +2,6 @@
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia/$1/lib/netcoreapp2.0/
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia/$1/lib/netstandard2.0/
- cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia.gtk3/$1/lib/netstandard2.0/
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia.skia/$1/lib/netstandard2.0/
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia.native/$1/lib/netstandard2.0/
diff --git a/src/Avalonia.Animation/Animatable.cs b/src/Avalonia.Animation/Animatable.cs
index 3a3d00b94a..2c321b8b28 100644
--- a/src/Avalonia.Animation/Animatable.cs
+++ b/src/Avalonia.Animation/Animatable.cs
@@ -45,16 +45,17 @@ namespace Avalonia.Animation
{
get
{
- if (_transitions == null)
+ if (_transitions is null)
_transitions = new Transitions();
- if (_previousTransitions == null)
+ if (_previousTransitions is null)
_previousTransitions = new Dictionary();
return _transitions;
}
set
{
+
SetAndRaise(TransitionsProperty, ref _transitions, value);
}
}
@@ -66,18 +67,20 @@ namespace Avalonia.Animation
/// The event args.
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
- if (e.Priority != BindingPriority.Animation && Transitions != null && _previousTransitions != null)
- {
- var match = Transitions.FirstOrDefault(x => x.Property == e.Property);
+ if (_transitions is null || _previousTransitions is null || e.Priority == BindingPriority.Animation) return;
- if (match != null)
+ // PERF-SENSITIVE: Called on every property change. Don't use LINQ here (too many allocations).
+ foreach (var transition in Transitions)
+ {
+ if (transition.Property == e.Property)
{
if (_previousTransitions.TryGetValue(e.Property, out var dispose))
dispose.Dispose();
- var instance = match.Apply(this, Clock ?? Avalonia.Animation.Clock.GlobalClock, e.OldValue, e.NewValue);
+ var instance = transition.Apply(this, Clock ?? Avalonia.Animation.Clock.GlobalClock, e.OldValue, e.NewValue);
_previousTransitions[e.Property] = instance;
+ return;
}
}
}
diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index 94558c4367..8cc512d132 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -82,6 +82,7 @@ namespace Avalonia
set
{
+ VerifyAccess();
if (_inheritanceParent != value)
{
if (_inheritanceParent != null)
@@ -89,25 +90,33 @@ namespace Avalonia
_inheritanceParent.InheritablePropertyChanged -= ParentPropertyChanged;
}
- var properties = AvaloniaPropertyRegistry.Instance.GetRegistered(this)
- .Concat(AvaloniaPropertyRegistry.Instance.GetRegisteredAttached(this.GetType()));
- var inherited = (from property in properties
- where property.Inherits
- select new
- {
- Property = property,
- Value = GetValue(property),
- }).ToList();
-
+ var oldInheritanceParent = _inheritanceParent;
_inheritanceParent = value;
+ var valuestore = _values;
- foreach (var i in inherited)
+ foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegisteredInherited(GetType()))
{
- object newValue = GetValue(i.Property);
+ if (valuestore != null && valuestore.GetValue(property) != AvaloniaProperty.UnsetValue)
+ {
+ // if local value set there can be no change
+ continue;
+ }
+ // get the value as it would have been with the previous InheritanceParent
+ object oldValue;
+ if (oldInheritanceParent is AvaloniaObject aobj)
+ {
+ oldValue = aobj.GetValueOrDefaultUnchecked(property);
+ }
+ else
+ {
+ oldValue = ((IStyledPropertyAccessor)property).GetDefaultValue(GetType());
+ }
+
+ object newValue = GetDefaultValue(property);
- if (!Equals(i.Value, newValue))
+ if (!Equals(oldValue, newValue))
{
- RaisePropertyChanged(i.Property, i.Value, newValue, BindingPriority.LocalValue);
+ RaisePropertyChanged(property, oldValue, newValue, BindingPriority.LocalValue);
}
}
diff --git a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs
index 88b0201fcb..d718f5917c 100644
--- a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs
+++ b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs
@@ -26,6 +26,8 @@ namespace Avalonia
new Dictionary>();
private readonly Dictionary> _initializedCache =
new Dictionary>();
+ private readonly Dictionary> _inheritedCache =
+ new Dictionary>();
///
/// Gets the instance
@@ -103,6 +105,46 @@ namespace Avalonia
return result;
}
+ ///
+ /// Gets all inherited s registered on a type.
+ ///
+ /// The type.
+ /// A collection of definitions.
+ public IEnumerable GetRegisteredInherited(Type type)
+ {
+ Contract.Requires(type != null);
+
+ if (_inheritedCache.TryGetValue(type, out var result))
+ {
+ return result;
+ }
+
+ result = new List();
+ var visited = new HashSet();
+
+ foreach (var property in GetRegistered(type))
+ {
+ if (property.Inherits)
+ {
+ result.Add(property);
+ visited.Add(property);
+ }
+ }
+ foreach (var property in GetRegisteredAttached(type))
+ {
+ if (property.Inherits)
+ {
+ if (!visited.Contains(property))
+ {
+ result.Add(property);
+ }
+ }
+ }
+
+ _inheritedCache.Add(type, result);
+ return result;
+ }
+
///
/// Gets all s registered on a object.
///
@@ -230,6 +272,7 @@ namespace Avalonia
_registeredCache.Clear();
_initializedCache.Clear();
+ _inheritedCache.Clear();
}
///
@@ -266,6 +309,7 @@ namespace Avalonia
_attachedCache.Clear();
_initializedCache.Clear();
+ _inheritedCache.Clear();
}
internal void NotifyInitialized(AvaloniaObject o)
diff --git a/src/Avalonia.Base/BoxedValue.cs b/src/Avalonia.Base/BoxedValue.cs
new file mode 100644
index 0000000000..5fc515f299
--- /dev/null
+++ b/src/Avalonia.Base/BoxedValue.cs
@@ -0,0 +1,28 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+namespace Avalonia
+{
+ ///
+ /// Represents boxed value of type .
+ ///
+ /// Type of stored value.
+ internal readonly struct BoxedValue
+ {
+ public BoxedValue(T value)
+ {
+ Boxed = value;
+ Typed = value;
+ }
+
+ ///
+ /// Boxed value.
+ ///
+ public object Boxed { get; }
+
+ ///
+ /// Typed value.
+ ///
+ public T Typed { get; }
+ }
+}
diff --git a/src/Avalonia.Base/PriorityBindingEntry.cs b/src/Avalonia.Base/PriorityBindingEntry.cs
index d4a47306a7..95add0dfac 100644
--- a/src/Avalonia.Base/PriorityBindingEntry.cs
+++ b/src/Avalonia.Base/PriorityBindingEntry.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
+using System.Runtime.ExceptionServices;
using Avalonia.Data;
using Avalonia.Threading;
@@ -10,9 +11,9 @@ namespace Avalonia
///
/// A registered binding in a .
///
- internal class PriorityBindingEntry : IDisposable
+ internal class PriorityBindingEntry : IDisposable, IObserver