diff --git a/Avalonia.sln b/Avalonia.sln
index 539ba04728..7b4a359f06 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -134,6 +134,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.NetCore", "s
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
ProjectSection(SolutionItems) = preProject
+ build\Base.props = build\Base.props
+ build\Binding.props = build\Binding.props
build\JetBrains.Annotations.props = build\JetBrains.Annotations.props
build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props
build\Magick.NET-Q16-AnyCPU.props = build\Magick.NET-Q16-AnyCPU.props
diff --git a/build/Binding.props b/build/Binding.props
new file mode 100644
index 0000000000..a512ee1d9c
--- /dev/null
+++ b/build/Binding.props
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
index 6f3b8361cd..f9d6a72a3a 100644
--- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
@@ -2,12 +2,14 @@ using Avalonia.Controls;
using Avalonia.LogicalTree;
using Avalonia.Markup;
using Avalonia.Markup.Xaml;
-using Avalonia.Markup.Xaml.Data;
+using Avalonia.Markup.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Avalonia.Data.Converters;
+using Avalonia.Data;
namespace ControlCatalog.Pages
{
diff --git a/samples/RenderTest/Pages/AnimationsPage.xaml b/samples/RenderTest/Pages/AnimationsPage.xaml
index 415c08728f..5287e4e373 100644
--- a/samples/RenderTest/Pages/AnimationsPage.xaml
+++ b/samples/RenderTest/Pages/AnimationsPage.xaml
@@ -48,13 +48,13 @@
PlaybackDirection="AlternateReverse"
Easing="SineEaseInOut">
-
+
-
+
-
+
@@ -63,8 +63,8 @@
-
-
+
+
@@ -76,8 +76,8 @@
Easing="QuadraticEaseInOut"
RepeatCount="Loop">
-
-
+
+
@@ -86,7 +86,7 @@
-
+
@@ -95,10 +95,10 @@
-
+
-
+
diff --git a/samples/RenderTest/Pages/ClippingPage.xaml b/samples/RenderTest/Pages/ClippingPage.xaml
index 434468888a..2e7944b0fc 100644
--- a/samples/RenderTest/Pages/ClippingPage.xaml
+++ b/samples/RenderTest/Pages/ClippingPage.xaml
@@ -10,7 +10,7 @@
-
+
diff --git a/src/Android/Avalonia.Android/Resources/Resource.Designer.cs b/src/Android/Avalonia.Android/Resources/Resource.Designer.cs
index 80cbbc51ec..e66c2800d3 100644
--- a/src/Android/Avalonia.Android/Resources/Resource.Designer.cs
+++ b/src/Android/Avalonia.Android/Resources/Resource.Designer.cs
@@ -40,11 +40,14 @@ namespace Avalonia.Android
public partial class String
{
+ // aapt resource value: 0x7f020002
+ public static int ApplicationName = 2130837506;
+
// aapt resource value: 0x7f020001
- public static int ApplicationName = 2130837505;
+ public static int Hello = 2130837505;
// aapt resource value: 0x7f020000
- public static int Hello = 2130837504;
+ public static int library_name = 2130837504;
static String()
{
diff --git a/src/Avalonia.Animation/Animation.cs b/src/Avalonia.Animation/Animation.cs
index 525be53fc2..aa436f5f4e 100644
--- a/src/Avalonia.Animation/Animation.cs
+++ b/src/Avalonia.Animation/Animation.cs
@@ -18,6 +18,28 @@ namespace Avalonia.Animation
///
public class Animation : AvaloniaList, IDisposable, IAnimation
{
+ private readonly static List<(Func Condition, Type Animator)> Animators = new List<(Func, Type)>
+ {
+ ( prop => typeof(double).IsAssignableFrom(prop.PropertyType), typeof(DoubleAnimator) )
+ };
+
+ public static void RegisterAnimator(Func condition)
+ where TAnimator: IAnimator
+ {
+ Animators.Insert(0, (condition, typeof(TAnimator)));
+ }
+
+ private static Type GetAnimatorType(AvaloniaProperty property)
+ {
+ foreach (var (condition, type) in Animators)
+ {
+ if (condition(property))
+ {
+ return type;
+ }
+ }
+ return null;
+ }
private bool _isChildrenChanged = false;
private List _subscription = new List();
@@ -67,14 +89,13 @@ namespace Avalonia.Animation
{
foreach (var setter in keyframe)
{
- var custAttr = setter.GetType()
- .GetCustomAttributes()
- .Where(p => p.GetType() == typeof(AnimatorAttribute));
+ var handler = GetAnimatorType(setter.Property);
- if (!custAttr.Any())
- throw new InvalidProgramException($"Type {setter.GetType()} doesn't have Animator attribute.");
+ if (handler == null)
+ {
+ throw new InvalidOperationException($"No animator registered for the property {setter.Property}. Add an animator to the Animation.Animators collection that matches this property to animate it.");
+ }
- var handler = ((AnimatorAttribute)custAttr.First()).HandlerType;
if (!handlerList.Contains((handler, setter.Property)))
handlerList.Add((handler, setter.Property));
diff --git a/src/Avalonia.Animation/AnimationSetter.cs b/src/Avalonia.Animation/AnimationSetter.cs
deleted file mode 100644
index 1194e4606b..0000000000
--- a/src/Avalonia.Animation/AnimationSetter.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Linq;
-using System.Reactive.Linq;
-using System.Diagnostics;
-using Avalonia.Animation.Utils;
-using Avalonia.Data;
-
-namespace Avalonia.Animation
-{
- public abstract class AnimationSetter : IAnimationSetter
- {
- public AvaloniaProperty Property { get; set; }
- public object Value { get; set; }
- }
-}
diff --git a/src/Avalonia.Animation/AnimatorAttribute.cs b/src/Avalonia.Animation/AnimatorAttribute.cs
deleted file mode 100644
index 58ee823a87..0000000000
--- a/src/Avalonia.Animation/AnimatorAttribute.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-
-namespace Avalonia.Animation
-{
- ///
- /// Attribute for objects
- /// that maps the setter to it's .
- ///
- public class AnimatorAttribute : Attribute
- {
- public Type HandlerType;
-
- public AnimatorAttribute(Type handler)
- {
- this.HandlerType = handler;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Avalonia.Animation/DoubleSetter.cs b/src/Avalonia.Animation/DoubleSetter.cs
deleted file mode 100644
index e524324a8c..0000000000
--- a/src/Avalonia.Animation/DoubleSetter.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Linq;
-using System.Reactive.Linq;
-using System.Diagnostics;
-using Avalonia.Animation.Utils;
-using Avalonia.Data;
-
-namespace Avalonia.Animation
-{
- ///
- /// Setter that handles properties
- /// in the target.
- ///
- [Animator(typeof(DoubleAnimator))]
- public class DoubleSetter : AnimationSetter
- {
-
- }
-}
\ No newline at end of file
diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj
index 35adcbeb92..26397a6f32 100644
--- a/src/Avalonia.Base/Avalonia.Base.csproj
+++ b/src/Avalonia.Base/Avalonia.Base.csproj
@@ -5,6 +5,7 @@
Avalonia
+
\ No newline at end of file
diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index 1a2db9fc3d..48e72db126 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -703,7 +703,7 @@ namespace Avalonia
/// The default value.
private object GetDefaultValue(AvaloniaProperty property)
{
- if (property.Inherits && _inheritanceParent is AvaloniaObject aobj)
+ if (property.Inherits && InheritanceParent is AvaloniaObject aobj)
return aobj.GetValueInternal(property);
return ((IStyledPropertyAccessor) property).GetDefaultValue(GetType());
}
diff --git a/src/Avalonia.Base/Collections/AvaloniaDictionary.cs b/src/Avalonia.Base/Collections/AvaloniaDictionary.cs
index 84ac85d3db..e8dc2a5ed7 100644
--- a/src/Avalonia.Base/Collections/AvaloniaDictionary.cs
+++ b/src/Avalonia.Base/Collections/AvaloniaDictionary.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
+using Avalonia.Data.Core;
namespace Avalonia.Collections
{
@@ -116,8 +117,8 @@ namespace Avalonia.Collections
_inner = new Dictionary();
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]"));
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(CommonPropertyNames.IndexerName));
if (CollectionChanged != null)
diff --git a/src/Avalonia.Base/Data/BindingNotification.cs b/src/Avalonia.Base/Data/BindingNotification.cs
index 5510a73b91..5d3e6b26f4 100644
--- a/src/Avalonia.Base/Data/BindingNotification.cs
+++ b/src/Avalonia.Base/Data/BindingNotification.cs
@@ -171,8 +171,7 @@ namespace Avalonia.Data
///
public static object ExtractError(object o)
{
- var notification = o as BindingNotification;
- return notification != null ? notification.Error : o;
+ return o is BindingNotification notification ? notification.Error : o;
}
///
diff --git a/src/Markup/Avalonia.Markup/AlwaysEnabledDelegateCommand.cs b/src/Avalonia.Base/Data/Converters/AlwaysEnabledDelegateCommand.cs
similarity index 97%
rename from src/Markup/Avalonia.Markup/AlwaysEnabledDelegateCommand.cs
rename to src/Avalonia.Base/Data/Converters/AlwaysEnabledDelegateCommand.cs
index 48db99b43c..d2fb48ffb8 100644
--- a/src/Markup/Avalonia.Markup/AlwaysEnabledDelegateCommand.cs
+++ b/src/Avalonia.Base/Data/Converters/AlwaysEnabledDelegateCommand.cs
@@ -6,7 +6,7 @@ using System.Reflection;
using System.Text;
using System.Windows.Input;
-namespace Avalonia.Markup
+namespace Avalonia.Data.Converters
{
class AlwaysEnabledDelegateCommand : ICommand
{
diff --git a/src/Markup/Avalonia.Markup/BoolConverters.cs b/src/Avalonia.Base/Data/Converters/BoolConverters.cs
similarity index 94%
rename from src/Markup/Avalonia.Markup/BoolConverters.cs
rename to src/Avalonia.Base/Data/Converters/BoolConverters.cs
index e049dccc06..6b429e1087 100644
--- a/src/Markup/Avalonia.Markup/BoolConverters.cs
+++ b/src/Avalonia.Base/Data/Converters/BoolConverters.cs
@@ -3,7 +3,7 @@
using System.Linq;
-namespace Avalonia.Markup
+namespace Avalonia.Data.Converters
{
///
/// Provides a set of useful s for working with string values.
diff --git a/src/Markup/Avalonia.Markup/DefaultValueConverter.cs b/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs
similarity index 98%
rename from src/Markup/Avalonia.Markup/DefaultValueConverter.cs
rename to src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs
index 28d64eb561..ec75076892 100644
--- a/src/Markup/Avalonia.Markup/DefaultValueConverter.cs
+++ b/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs
@@ -7,7 +7,7 @@ using Avalonia.Data;
using Avalonia.Utilities;
using System.Windows.Input;
-namespace Avalonia.Markup
+namespace Avalonia.Data.Converters
{
///
/// Provides a default set of value conversions for bindings that do not specify a value
diff --git a/src/Markup/Avalonia.Markup/FuncMultiValueConverter.cs b/src/Avalonia.Base/Data/Converters/FuncMultiValueConverter.cs
similarity index 97%
rename from src/Markup/Avalonia.Markup/FuncMultiValueConverter.cs
rename to src/Avalonia.Base/Data/Converters/FuncMultiValueConverter.cs
index 75aace0bd9..6e1c4cb0e3 100644
--- a/src/Markup/Avalonia.Markup/FuncMultiValueConverter.cs
+++ b/src/Avalonia.Base/Data/Converters/FuncMultiValueConverter.cs
@@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-namespace Avalonia.Markup
+namespace Avalonia.Data.Converters
{
///
/// A general purpose that uses a
diff --git a/src/Markup/Avalonia.Markup/FuncValueConverter.cs b/src/Avalonia.Base/Data/Converters/FuncValueConverter.cs
similarity index 97%
rename from src/Markup/Avalonia.Markup/FuncValueConverter.cs
rename to src/Avalonia.Base/Data/Converters/FuncValueConverter.cs
index 109de9371d..b747587b4a 100644
--- a/src/Markup/Avalonia.Markup/FuncValueConverter.cs
+++ b/src/Avalonia.Base/Data/Converters/FuncValueConverter.cs
@@ -5,7 +5,7 @@ using System;
using System.Globalization;
using Avalonia.Utilities;
-namespace Avalonia.Markup
+namespace Avalonia.Data.Converters
{
///
/// A general purpose that uses a
diff --git a/src/Markup/Avalonia.Markup/IMultiValueConverter.cs b/src/Avalonia.Base/Data/Converters/IMultiValueConverter.cs
similarity index 97%
rename from src/Markup/Avalonia.Markup/IMultiValueConverter.cs
rename to src/Avalonia.Base/Data/Converters/IMultiValueConverter.cs
index be75dabb1c..3f84fcb3e7 100644
--- a/src/Markup/Avalonia.Markup/IMultiValueConverter.cs
+++ b/src/Avalonia.Base/Data/Converters/IMultiValueConverter.cs
@@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
-namespace Avalonia.Markup
+namespace Avalonia.Data.Converters
{
///
/// Converts multi-binding inputs to a final value.
diff --git a/src/Markup/Avalonia.Markup/IValueConverter.cs b/src/Avalonia.Base/Data/Converters/IValueConverter.cs
similarity index 98%
rename from src/Markup/Avalonia.Markup/IValueConverter.cs
rename to src/Avalonia.Base/Data/Converters/IValueConverter.cs
index 10d5c626c2..b55a2c4fe8 100644
--- a/src/Markup/Avalonia.Markup/IValueConverter.cs
+++ b/src/Avalonia.Base/Data/Converters/IValueConverter.cs
@@ -5,7 +5,7 @@ using System;
using System.Globalization;
using Avalonia.Data;
-namespace Avalonia.Markup
+namespace Avalonia.Data.Converters
{
///
/// Converts a binding value.
diff --git a/src/Markup/Avalonia.Markup/StringConverters.cs b/src/Avalonia.Base/Data/Converters/StringConverters.cs
similarity index 96%
rename from src/Markup/Avalonia.Markup/StringConverters.cs
rename to src/Avalonia.Base/Data/Converters/StringConverters.cs
index fda79c76a3..470f0d2289 100644
--- a/src/Markup/Avalonia.Markup/StringConverters.cs
+++ b/src/Avalonia.Base/Data/Converters/StringConverters.cs
@@ -5,7 +5,7 @@ using System;
using System.Globalization;
using Avalonia.Utilities;
-namespace Avalonia.Markup
+namespace Avalonia.Data.Converters
{
///
/// Provides a set of useful s for working with string values.
diff --git a/src/Markup/Avalonia.Markup/Data/BindingExpression.cs b/src/Avalonia.Base/Data/Core/BindingExpression.cs
similarity index 99%
rename from src/Markup/Avalonia.Markup/Data/BindingExpression.cs
rename to src/Avalonia.Base/Data/Core/BindingExpression.cs
index 5b9959e42e..4b41d1568c 100644
--- a/src/Markup/Avalonia.Markup/Data/BindingExpression.cs
+++ b/src/Avalonia.Base/Data/Core/BindingExpression.cs
@@ -5,11 +5,11 @@ using System;
using System.Globalization;
using System.Reactive.Linq;
using System.Reactive.Subjects;
-using Avalonia.Data;
+using Avalonia.Data.Converters;
using Avalonia.Logging;
using Avalonia.Utilities;
-namespace Avalonia.Markup.Data
+namespace Avalonia.Data.Core
{
///
/// Binds to an expression on an object using a type value converter to convert the values
diff --git a/src/Markup/Avalonia.Markup/Data/CommonPropertyNames.cs b/src/Avalonia.Base/Data/Core/CommonPropertyNames.cs
similarity index 89%
rename from src/Markup/Avalonia.Markup/Data/CommonPropertyNames.cs
rename to src/Avalonia.Base/Data/Core/CommonPropertyNames.cs
index f91940baf7..6760c3f259 100644
--- a/src/Markup/Avalonia.Markup/Data/CommonPropertyNames.cs
+++ b/src/Avalonia.Base/Data/Core/CommonPropertyNames.cs
@@ -1,7 +1,7 @@
// 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.Markup.Data
+namespace Avalonia.Data.Core
{
public static class CommonPropertyNames
{
diff --git a/src/Markup/Avalonia.Markup/Data/EmptyExpressionNode.cs b/src/Avalonia.Base/Data/Core/EmptyExpressionNode.cs
similarity index 94%
rename from src/Markup/Avalonia.Markup/Data/EmptyExpressionNode.cs
rename to src/Avalonia.Base/Data/Core/EmptyExpressionNode.cs
index 02ecd817da..93e0d5947a 100644
--- a/src/Markup/Avalonia.Markup/Data/EmptyExpressionNode.cs
+++ b/src/Avalonia.Base/Data/Core/EmptyExpressionNode.cs
@@ -4,7 +4,7 @@
using System;
using System.Reactive.Linq;
-namespace Avalonia.Markup.Data
+namespace Avalonia.Data.Core
{
internal class EmptyExpressionNode : ExpressionNode
{
diff --git a/src/Markup/Avalonia.Markup/Data/ExpressionNode.cs b/src/Avalonia.Base/Data/Core/ExpressionNode.cs
similarity index 99%
rename from src/Markup/Avalonia.Markup/Data/ExpressionNode.cs
rename to src/Avalonia.Base/Data/Core/ExpressionNode.cs
index 56c0072eaa..ae70cacdba 100644
--- a/src/Markup/Avalonia.Markup/Data/ExpressionNode.cs
+++ b/src/Avalonia.Base/Data/Core/ExpressionNode.cs
@@ -7,7 +7,7 @@ using System.Reactive.Linq;
using System.Reactive.Subjects;
using Avalonia.Data;
-namespace Avalonia.Markup.Data
+namespace Avalonia.Data.Core
{
internal abstract class ExpressionNode : ISubject