diff --git a/Avalonia.sln b/Avalonia.sln index 47ee4c1ad9..91413fc5ee 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -138,6 +138,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{74487168 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..65be8c801e 100644 --- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs @@ -2,12 +2,13 @@ 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; namespace ControlCatalog.Pages { 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.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/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 { diff --git a/src/Markup/Avalonia.Markup/Data/ExpressionNodeBuilder.cs b/src/Avalonia.Base/Data/Core/ExpressionNodeBuilder.cs similarity index 92% rename from src/Markup/Avalonia.Markup/Data/ExpressionNodeBuilder.cs rename to src/Avalonia.Base/Data/Core/ExpressionNodeBuilder.cs index 013299c1d7..8e9e9fc3c1 100644 --- a/src/Markup/Avalonia.Markup/Data/ExpressionNodeBuilder.cs +++ b/src/Avalonia.Base/Data/Core/ExpressionNodeBuilder.cs @@ -2,9 +2,9 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using Avalonia.Markup.Data.Parsers; +using Avalonia.Data.Core.Parsers; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { internal static class ExpressionNodeBuilder { diff --git a/src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs b/src/Avalonia.Base/Data/Core/ExpressionObserver.cs similarity index 90% rename from src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs rename to src/Avalonia.Base/Data/Core/ExpressionObserver.cs index dd9718a0f6..7719f93a02 100644 --- a/src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs +++ b/src/Avalonia.Base/Data/Core/ExpressionObserver.cs @@ -8,9 +8,9 @@ using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reactive.Subjects; using Avalonia.Data; -using Avalonia.Markup.Data.Plugins; +using Avalonia.Data.Core.Plugins; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { /// /// Observes and sets the value of an expression on an object. @@ -245,40 +245,35 @@ namespace Avalonia.Markup.Data private object Translate(object o) { - var weak = o as WeakReference; - - if (weak != null) + if (o is WeakReference weak) { return weak.Target; } - else + else if (BindingNotification.ExtractError(o) is MarkupBindingChainException broken) { - var broken = BindingNotification.ExtractError(o) as MarkupBindingChainException; - - if (broken != null) - { - broken.Commit(Description); - } - return o; + broken.Commit(Description); } + + return o; } private IDisposable StartRoot() { - var observable = _root as IObservable; - - if (observable != null) + switch (_root) { - return observable.Subscribe( - x => _node.Target = new WeakReference(x != AvaloniaProperty.UnsetValue ? x : null), - _ => _finished.OnNext(Unit.Default), - () => _finished.OnNext(Unit.Default)); - } - else - { - _node.Target = (WeakReference)_root; - return Disposable.Empty; + case IObservable observable: + return observable.Subscribe( + x => _node.Target = new WeakReference(x != AvaloniaProperty.UnsetValue ? x : null), + _ => _finished.OnNext(Unit.Default), + () => _finished.OnNext(Unit.Default)); + case WeakReference weak: + _node.Target = weak; + break; + default: + throw new AvaloniaInternalException("The ExpressionObserver._root member should only be either an observable or WeakReference."); } + + return Disposable.Empty; } } } diff --git a/src/Markup/Avalonia.Markup/Data/ExpressionParseException.cs b/src/Avalonia.Base/Data/Core/ExpressionParseException.cs similarity index 93% rename from src/Markup/Avalonia.Markup/Data/ExpressionParseException.cs rename to src/Avalonia.Base/Data/Core/ExpressionParseException.cs index d06bdd1e52..3d7bce4080 100644 --- a/src/Markup/Avalonia.Markup/Data/ExpressionParseException.cs +++ b/src/Avalonia.Base/Data/Core/ExpressionParseException.cs @@ -2,9 +2,9 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using Avalonia.Markup.Data.Parsers; +using Avalonia.Data.Core.Parsers; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { /// /// Exception thrown when could not parse the provided diff --git a/src/Markup/Avalonia.Markup/Data/ISettableNode.cs b/src/Avalonia.Base/Data/Core/ISettableNode.cs similarity index 90% rename from src/Markup/Avalonia.Markup/Data/ISettableNode.cs rename to src/Avalonia.Base/Data/Core/ISettableNode.cs index 8ee4f1de20..7788407833 100644 --- a/src/Markup/Avalonia.Markup/Data/ISettableNode.cs +++ b/src/Avalonia.Base/Data/Core/ISettableNode.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { interface ISettableNode { diff --git a/src/Markup/Avalonia.Markup/Data/ITransformNode.cs b/src/Avalonia.Base/Data/Core/ITransformNode.cs similarity index 83% rename from src/Markup/Avalonia.Markup/Data/ITransformNode.cs rename to src/Avalonia.Base/Data/Core/ITransformNode.cs index f33ecd3722..7638db8302 100644 --- a/src/Markup/Avalonia.Markup/Data/ITransformNode.cs +++ b/src/Avalonia.Base/Data/Core/ITransformNode.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { interface ITransformNode { diff --git a/src/Markup/Avalonia.Markup/Data/IndexerNode.cs b/src/Avalonia.Base/Data/Core/IndexerNode.cs similarity index 99% rename from src/Markup/Avalonia.Markup/Data/IndexerNode.cs rename to src/Avalonia.Base/Data/Core/IndexerNode.cs index 4e2914a148..47e82fa2d3 100644 --- a/src/Markup/Avalonia.Markup/Data/IndexerNode.cs +++ b/src/Avalonia.Base/Data/Core/IndexerNode.cs @@ -13,7 +13,7 @@ using System.Reflection; using System.Reactive.Linq; using Avalonia.Data; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { internal class IndexerNode : ExpressionNode, ISettableNode { diff --git a/src/Markup/Avalonia.Markup/Data/LogicalNotNode.cs b/src/Avalonia.Base/Data/Core/LogicalNotNode.cs similarity index 98% rename from src/Markup/Avalonia.Markup/Data/LogicalNotNode.cs rename to src/Avalonia.Base/Data/Core/LogicalNotNode.cs index ae68867e82..f277005cec 100644 --- a/src/Markup/Avalonia.Markup/Data/LogicalNotNode.cs +++ b/src/Avalonia.Base/Data/Core/LogicalNotNode.cs @@ -5,7 +5,7 @@ using System; using System.Globalization; using Avalonia.Data; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { internal class LogicalNotNode : ExpressionNode, ITransformNode { diff --git a/src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs b/src/Avalonia.Base/Data/Core/MarkupBindingChainException.cs similarity index 95% rename from src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs rename to src/Avalonia.Base/Data/Core/MarkupBindingChainException.cs index ddfcf531eb..a9b31c7617 100644 --- a/src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs +++ b/src/Avalonia.Base/Data/Core/MarkupBindingChainException.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using Avalonia.Data; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { internal class MarkupBindingChainException : BindingChainException { diff --git a/src/Markup/Avalonia.Markup/Data/Parsers/ArgumentListParser.cs b/src/Avalonia.Base/Data/Core/Parsers/ArgumentListParser.cs similarity index 97% rename from src/Markup/Avalonia.Markup/Data/Parsers/ArgumentListParser.cs rename to src/Avalonia.Base/Data/Core/Parsers/ArgumentListParser.cs index 05b3b29be0..17200a62b1 100644 --- a/src/Markup/Avalonia.Markup/Data/Parsers/ArgumentListParser.cs +++ b/src/Avalonia.Base/Data/Core/Parsers/ArgumentListParser.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Text; -namespace Avalonia.Markup.Data.Parsers +namespace Avalonia.Data.Core.Parsers { internal static class ArgumentListParser { diff --git a/src/Markup/Avalonia.Markup/Data/Parsers/ExpressionParser.cs b/src/Avalonia.Base/Data/Core/Parsers/ExpressionParser.cs similarity index 99% rename from src/Markup/Avalonia.Markup/Data/Parsers/ExpressionParser.cs rename to src/Avalonia.Base/Data/Core/Parsers/ExpressionParser.cs index f31f6eccb7..5c74c5cd13 100644 --- a/src/Markup/Avalonia.Markup/Data/Parsers/ExpressionParser.cs +++ b/src/Avalonia.Base/Data/Core/Parsers/ExpressionParser.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; -namespace Avalonia.Markup.Data.Parsers +namespace Avalonia.Data.Core.Parsers { internal class ExpressionParser { diff --git a/src/Markup/Avalonia.Markup/Data/Parsers/IdentifierParser.cs b/src/Avalonia.Base/Data/Core/Parsers/IdentifierParser.cs similarity index 97% rename from src/Markup/Avalonia.Markup/Data/Parsers/IdentifierParser.cs rename to src/Avalonia.Base/Data/Core/Parsers/IdentifierParser.cs index fa9051af06..b0a9ff4df2 100644 --- a/src/Markup/Avalonia.Markup/Data/Parsers/IdentifierParser.cs +++ b/src/Avalonia.Base/Data/Core/Parsers/IdentifierParser.cs @@ -4,7 +4,7 @@ using System.Globalization; using System.Text; -namespace Avalonia.Markup.Data.Parsers +namespace Avalonia.Data.Core.Parsers { internal static class IdentifierParser { diff --git a/src/Markup/Avalonia.Markup/Data/Parsers/Reader.cs b/src/Avalonia.Base/Data/Core/Parsers/Reader.cs similarity index 95% rename from src/Markup/Avalonia.Markup/Data/Parsers/Reader.cs rename to src/Avalonia.Base/Data/Core/Parsers/Reader.cs index 414648a10c..14187c769a 100644 --- a/src/Markup/Avalonia.Markup/Data/Parsers/Reader.cs +++ b/src/Avalonia.Base/Data/Core/Parsers/Reader.cs @@ -3,7 +3,7 @@ using System; -namespace Avalonia.Markup.Data.Parsers +namespace Avalonia.Data.Core.Parsers { internal class Reader { diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/AvaloniaPropertyAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/AvaloniaPropertyAccessorPlugin.cs similarity index 99% rename from src/Markup/Avalonia.Markup/Data/Plugins/AvaloniaPropertyAccessorPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/AvaloniaPropertyAccessorPlugin.cs index ac64459dd7..8cbcaa8233 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/AvaloniaPropertyAccessorPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/AvaloniaPropertyAccessorPlugin.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Reactive.Linq; using Avalonia.Data; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Reads a property from a . diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/DataAnnotationsValidationPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs similarity index 98% rename from src/Markup/Avalonia.Markup/Data/Plugins/DataAnnotationsValidationPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs index 859438636a..47e4d91e13 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/DataAnnotationsValidationPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Reflection; using Avalonia.Data; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Validates properties on that have s. diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/DataValidatiorBase.cs b/src/Avalonia.Base/Data/Core/Plugins/DataValidatiorBase.cs similarity index 98% rename from src/Markup/Avalonia.Markup/Data/Plugins/DataValidatiorBase.cs rename to src/Avalonia.Base/Data/Core/Plugins/DataValidatiorBase.cs index 95d269f437..bd429f04d6 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/DataValidatiorBase.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/DataValidatiorBase.cs @@ -4,7 +4,7 @@ using System; using Avalonia.Data; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Base class for data validators. diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/ExceptionValidationPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/ExceptionValidationPlugin.cs similarity index 97% rename from src/Markup/Avalonia.Markup/Data/Plugins/ExceptionValidationPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/ExceptionValidationPlugin.cs index e0b6bcfd7c..35f9f7e59a 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/ExceptionValidationPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/ExceptionValidationPlugin.cs @@ -5,7 +5,7 @@ using Avalonia.Data; using System; using System.Reflection; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Validates properties that report errors by throwing exceptions. diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/IDataValidationPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/IDataValidationPlugin.cs similarity index 97% rename from src/Markup/Avalonia.Markup/Data/Plugins/IDataValidationPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/IDataValidationPlugin.cs index 0952e2edab..c55917b088 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/IDataValidationPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/IDataValidationPlugin.cs @@ -4,7 +4,7 @@ using System; using Avalonia.Data; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Defines how data validation is observed by an . diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/IPropertyAccessor.cs b/src/Avalonia.Base/Data/Core/Plugins/IPropertyAccessor.cs similarity index 97% rename from src/Markup/Avalonia.Markup/Data/Plugins/IPropertyAccessor.cs rename to src/Avalonia.Base/Data/Core/Plugins/IPropertyAccessor.cs index 9e686baf10..d7dda57a72 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/IPropertyAccessor.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/IPropertyAccessor.cs @@ -4,7 +4,7 @@ using System; using Avalonia.Data; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Defines an accessor to a property on an object returned by a diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/IPropertyAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/IPropertyAccessorPlugin.cs similarity index 97% rename from src/Markup/Avalonia.Markup/Data/Plugins/IPropertyAccessorPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/IPropertyAccessorPlugin.cs index ebfdf6ebe4..539f518083 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/IPropertyAccessorPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/IPropertyAccessorPlugin.cs @@ -3,7 +3,7 @@ using System; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Defines how a member is read, written and observed by an diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/IStreamPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/IStreamPlugin.cs similarity index 96% rename from src/Markup/Avalonia.Markup/Data/Plugins/IStreamPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/IStreamPlugin.cs index efb2e2d93a..b80d9d75c8 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/IStreamPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/IStreamPlugin.cs @@ -3,7 +3,7 @@ using System; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Defines a plugin that handles the '^' stream binding operator. diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/IndeiValidationPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs similarity index 99% rename from src/Markup/Avalonia.Markup/Data/Plugins/IndeiValidationPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs index 82bc87c207..436046f3fa 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/IndeiValidationPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs @@ -8,7 +8,7 @@ using System.Linq; using Avalonia.Data; using Avalonia.Utilities; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Validates properties on objects that implement . diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/InpcPropertyAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs similarity index 99% rename from src/Markup/Avalonia.Markup/Data/Plugins/InpcPropertyAccessorPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs index 3bdaba6fd9..ba4e60eb74 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/InpcPropertyAccessorPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs @@ -10,7 +10,7 @@ using Avalonia.Data; using Avalonia.Logging; using Avalonia.Utilities; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Reads a property from a standard C# object that optionally supports the diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/MethodAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/MethodAccessorPlugin.cs similarity index 98% rename from src/Markup/Avalonia.Markup/Data/Plugins/MethodAccessorPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/MethodAccessorPlugin.cs index db0d3e0299..b2b3a107fa 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/MethodAccessorPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/MethodAccessorPlugin.cs @@ -5,7 +5,7 @@ using Avalonia.Data; using System.Reflection; using System.Linq; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { class MethodAccessorPlugin : IPropertyAccessorPlugin { diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/ObservableStreamPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/ObservableStreamPlugin.cs similarity index 96% rename from src/Markup/Avalonia.Markup/Data/Plugins/ObservableStreamPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/ObservableStreamPlugin.cs index a1da42d28f..14ca8ee79e 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/ObservableStreamPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/ObservableStreamPlugin.cs @@ -3,7 +3,7 @@ using System; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Handles binding to s for the '^' stream binding operator. diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/PropertyAccessorBase.cs b/src/Avalonia.Base/Data/Core/Plugins/PropertyAccessorBase.cs similarity index 98% rename from src/Markup/Avalonia.Markup/Data/Plugins/PropertyAccessorBase.cs rename to src/Avalonia.Base/Data/Core/Plugins/PropertyAccessorBase.cs index 9aa858e0eb..9cc78369a7 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/PropertyAccessorBase.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/PropertyAccessorBase.cs @@ -4,7 +4,7 @@ using System; using Avalonia.Data; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Defines a default base implementation for a . diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/PropertyError.cs b/src/Avalonia.Base/Data/Core/Plugins/PropertyError.cs similarity index 96% rename from src/Markup/Avalonia.Markup/Data/Plugins/PropertyError.cs rename to src/Avalonia.Base/Data/Core/Plugins/PropertyError.cs index b351ef39bd..647adc36cb 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/PropertyError.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/PropertyError.cs @@ -2,7 +2,7 @@ using System; using System.Reactive.Disposables; using Avalonia.Data; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// An that represents an error. diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/TaskStreamPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/TaskStreamPlugin.cs similarity index 98% rename from src/Markup/Avalonia.Markup/Data/Plugins/TaskStreamPlugin.cs rename to src/Avalonia.Base/Data/Core/Plugins/TaskStreamPlugin.cs index 02fe8104b8..cc9b3abd56 100644 --- a/src/Markup/Avalonia.Markup/Data/Plugins/TaskStreamPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/TaskStreamPlugin.cs @@ -9,7 +9,7 @@ using System.Reflection; using System.Threading.Tasks; using Avalonia.Data; -namespace Avalonia.Markup.Data.Plugins +namespace Avalonia.Data.Core.Plugins { /// /// Handles binding to s for the '^' stream binding operator. diff --git a/src/Markup/Avalonia.Markup/Data/PropertyAccessorNode.cs b/src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs similarity index 96% rename from src/Markup/Avalonia.Markup/Data/PropertyAccessorNode.cs rename to src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs index f6040d3f15..4dbff4602f 100644 --- a/src/Markup/Avalonia.Markup/Data/PropertyAccessorNode.cs +++ b/src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs @@ -6,9 +6,9 @@ using System.Linq; using System.Reactive.Disposables; using System.Reactive.Linq; using Avalonia.Data; -using Avalonia.Markup.Data.Plugins; +using Avalonia.Data.Core.Plugins; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { internal class PropertyAccessorNode : ExpressionNode, ISettableNode { diff --git a/src/Markup/Avalonia.Markup/Data/StreamNode.cs b/src/Avalonia.Base/Data/Core/StreamNode.cs similarity index 96% rename from src/Markup/Avalonia.Markup/Data/StreamNode.cs rename to src/Avalonia.Base/Data/Core/StreamNode.cs index ebcbfc9598..187c79af49 100644 --- a/src/Markup/Avalonia.Markup/Data/StreamNode.cs +++ b/src/Avalonia.Base/Data/Core/StreamNode.cs @@ -6,7 +6,7 @@ using System.Globalization; using Avalonia.Data; using System.Reactive.Linq; -namespace Avalonia.Markup.Data +namespace Avalonia.Data.Core { internal class StreamNode : ExpressionNode { diff --git a/src/Avalonia.Base/Properties/AssemblyInfo.cs b/src/Avalonia.Base/Properties/AssemblyInfo.cs index 0a276aa2aa..75d58f45d5 100644 --- a/src/Avalonia.Base/Properties/AssemblyInfo.cs +++ b/src/Avalonia.Base/Properties/AssemblyInfo.cs @@ -1,9 +1,10 @@ -// 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. using System.Reflection; using System.Runtime.CompilerServices; +using Avalonia.Metadata; +[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Data.Converters")] [assembly: InternalsVisibleTo("Avalonia.Base.UnitTests")] [assembly: InternalsVisibleTo("Avalonia.UnitTests")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] \ No newline at end of file diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index 8bfe8c25bd..1690ad97ae 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -32,6 +32,7 @@ + @@ -51,11 +52,11 @@ + + - - @@ -86,6 +87,5 @@ - \ No newline at end of file diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs index f3fac3faf7..c361372820 100644 --- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs +++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs @@ -2,7 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia.Controls; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Markup.Xaml.PortableXaml; using Avalonia.Platform; using Portable.Xaml; diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs index bc3caff3b9..131cb5a20b 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs @@ -10,7 +10,7 @@ namespace Avalonia.Markup.Xaml.Converters using Avalonia.Styling; using Portable.Xaml; using Portable.Xaml.ComponentModel; - using System.ComponentModel; + using System.ComponentModel; using Portable.Xaml.Markup; public class AvaloniaPropertyTypeConverter : TypeConverter diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/SelectorTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/SelectorTypeConverter.cs index 29ddcccd08..fb0131a9b4 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Converters/SelectorTypeConverter.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Converters/SelectorTypeConverter.cs @@ -3,12 +3,12 @@ using System; using System.Globalization; -using Avalonia.Markup.Xaml.Parsers; +using Avalonia.Markup.Parsers; namespace Avalonia.Markup.Xaml.Converters { using Portable.Xaml.ComponentModel; - using System.ComponentModel; + using System.ComponentModel; public class SelectorTypeConverter : TypeConverter { diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs index 6e8fe1e4c0..98203deebe 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs @@ -2,12 +2,13 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; using System; namespace Avalonia.Markup.Xaml.MarkupExtensions { using Avalonia.Controls; + using Avalonia.Data.Converters; + using Avalonia.Markup.Data; using Avalonia.Styling; using Portable.Xaml; using Portable.Xaml.ComponentModel; diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/RelativeSourceExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/RelativeSourceExtension.cs index 0b3345d6db..c9ec973f20 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/RelativeSourceExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/RelativeSourceExtension.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. -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; namespace Avalonia.Markup.Xaml.MarkupExtensions { diff --git a/src/Markup/Avalonia.Markup.Xaml/Data/ResourceInclude.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs similarity index 97% rename from src/Markup/Avalonia.Markup.Xaml/Data/ResourceInclude.cs rename to src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs index 035765fae0..75fac8aa92 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Data/ResourceInclude.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs @@ -4,7 +4,7 @@ using Avalonia.Controls; using Portable.Xaml.ComponentModel; using Portable.Xaml.Markup; -namespace Avalonia.Markup.Xaml.Data +namespace Avalonia.Markup.Xaml.MarkupExtensions { /// /// Loads a resource dictionary from a specified URL. diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs index 8e71c5f81b..dd1d697224 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticResourceExtension.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Reflection; using Avalonia.Controls; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Portable.Xaml; using Portable.Xaml.ComponentModel; using Portable.Xaml.Markup; diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs index c5fe83977f..c8fc8a41d1 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs @@ -2,14 +2,15 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; namespace Avalonia.Markup.Xaml.MarkupExtensions { using System; + using Avalonia.Data.Converters; + using Avalonia.Markup.Data; using Portable.Xaml.Markup; - [MarkupExtensionReturnType(typeof(Binding))] + [MarkupExtensionReturnType(typeof(IBinding))] public class TemplateBindingExtension : MarkupExtension { public TemplateBindingExtension() diff --git a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaRuntimeTypeProvider.cs b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaRuntimeTypeProvider.cs index b6ffac69ab..9cb2cc6cd8 100644 --- a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaRuntimeTypeProvider.cs +++ b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaRuntimeTypeProvider.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Avalonia.Controls; +using Avalonia.Markup.Data; using Avalonia.Markup.Xaml.Templates; using Avalonia.Media; using Avalonia.Metadata; @@ -35,7 +36,7 @@ namespace Avalonia.Markup.Xaml.Context typeof(Style).GetTypeInfo().Assembly, typeof(DataTemplate).GetTypeInfo().Assembly, typeof(SolidColorBrush).GetTypeInfo().Assembly, - typeof(IValueConverter).GetTypeInfo().Assembly, + typeof(Binding).GetTypeInfo().Assembly, }; private Dictionary> _namespaces = new Dictionary>(); diff --git a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs index fda5da902a..70402aa764 100644 --- a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs +++ b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs @@ -1,6 +1,6 @@ using Avalonia.Data; using Avalonia.Markup.Xaml.Context; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Markup.Xaml.MarkupExtensions; using Avalonia.Markup.Xaml.Styling; using Portable.Xaml; diff --git a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs index 59dbba7084..2194223cb7 100644 --- a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs +++ b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs @@ -1,6 +1,6 @@ using Avalonia.Controls; using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Metadata; using Avalonia.Styling; using Portable.Xaml; diff --git a/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs b/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs index 1b0e056baf..e67e994123 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs @@ -5,10 +5,8 @@ using System.Reflection; using Avalonia.Metadata; using System.Runtime.CompilerServices; -[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Data")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.MarkupExtensions")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Styling")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Templates")] -[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml", "Avalonia.Markup.Xaml.MarkupExtensions.Standard")] [assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests")] diff --git a/src/Markup/Avalonia.Markup.Xaml/Templates/MemberSelector.cs b/src/Markup/Avalonia.Markup.Xaml/Templates/MemberSelector.cs index 1581765132..aa3c359953 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Templates/MemberSelector.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Templates/MemberSelector.cs @@ -3,7 +3,7 @@ using Avalonia.Controls.Templates; using Avalonia.Data; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using System; using System.Reactive.Linq; diff --git a/src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs b/src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs index 883e177f8a..a733ef761c 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs @@ -6,8 +6,8 @@ using System.Reflection; using Avalonia.Controls; using Avalonia.Controls.Templates; using Avalonia.Data; +using Avalonia.Data.Core; using Avalonia.Markup.Data; -using Avalonia.Markup.Xaml.Data; using Avalonia.Metadata; namespace Avalonia.Markup.Xaml.Templates @@ -48,11 +48,6 @@ namespace Avalonia.Markup.Xaml.Templates return null; } - public bool IsExpanded(object item) - { - return true; - } - public IControl Build(object data) { var visualTreeForItem = TemplateContent.Load(Content); diff --git a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj index 56b8d46b64..02e49a4d73 100644 --- a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj +++ b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj @@ -4,7 +4,11 @@ + + + + - + \ No newline at end of file diff --git a/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs b/src/Markup/Avalonia.Markup/Data/Binding.cs similarity index 98% rename from src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs rename to src/Markup/Avalonia.Markup/Data/Binding.cs index c440a94935..bf44912bba 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs +++ b/src/Markup/Avalonia.Markup/Data/Binding.cs @@ -8,11 +8,12 @@ using System.Reactive.Linq; using System.Reflection; using Avalonia.Controls; using Avalonia.Data; +using Avalonia.Data.Converters; +using Avalonia.Data.Core; using Avalonia.LogicalTree; -using Avalonia.Markup.Data; using Avalonia.VisualTree; -namespace Avalonia.Markup.Xaml.Data +namespace Avalonia.Markup.Data { /// /// A XAML binding. @@ -84,7 +85,7 @@ namespace Avalonia.Markup.Xaml.Data /// public object Source { get; set; } - internal WeakReference DefaultAnchor { get; set; } + public WeakReference DefaultAnchor { get; set; } /// public InstancedBinding Initiate( diff --git a/src/Markup/Avalonia.Markup.Xaml/Data/DelayedBinding.cs b/src/Markup/Avalonia.Markup/Data/DelayedBinding.cs similarity index 99% rename from src/Markup/Avalonia.Markup.Xaml/Data/DelayedBinding.cs rename to src/Markup/Avalonia.Markup/Data/DelayedBinding.cs index 5ec40fe702..df16c02dab 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Data/DelayedBinding.cs +++ b/src/Markup/Avalonia.Markup/Data/DelayedBinding.cs @@ -9,7 +9,7 @@ using Avalonia.Controls; using Avalonia.Data; using Avalonia.Logging; -namespace Avalonia.Markup.Xaml.Data +namespace Avalonia.Markup.Data { /// /// Provides delayed bindings for controls. diff --git a/src/Markup/Avalonia.Markup.Xaml/Data/MultiBinding.cs b/src/Markup/Avalonia.Markup/Data/MultiBinding.cs similarity index 98% rename from src/Markup/Avalonia.Markup.Xaml/Data/MultiBinding.cs rename to src/Markup/Avalonia.Markup/Data/MultiBinding.cs index 3c29ed3a39..4c7d9396ac 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Data/MultiBinding.cs +++ b/src/Markup/Avalonia.Markup/Data/MultiBinding.cs @@ -9,9 +9,10 @@ using System.Reactive.Linq; using System.Reactive.Subjects; using Avalonia.Controls; using Avalonia.Data; +using Avalonia.Data.Converters; using Avalonia.Metadata; -namespace Avalonia.Markup.Xaml.Data +namespace Avalonia.Markup.Data { /// /// A XAML binding that calculates an aggregate value from multiple child . diff --git a/src/Markup/Avalonia.Markup.Xaml/Data/RelativeSource.cs b/src/Markup/Avalonia.Markup/Data/RelativeSource.cs similarity index 98% rename from src/Markup/Avalonia.Markup.Xaml/Data/RelativeSource.cs rename to src/Markup/Avalonia.Markup/Data/RelativeSource.cs index 825d3b8ba5..ffddb7ee03 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Data/RelativeSource.cs +++ b/src/Markup/Avalonia.Markup/Data/RelativeSource.cs @@ -2,8 +2,9 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using Avalonia.Controls; -namespace Avalonia.Markup.Xaml.Data +namespace Avalonia.Markup.Data { /// /// Defines the mode of a object. diff --git a/src/Markup/Avalonia.Markup.Xaml/Parsers/SelectorGrammar.cs b/src/Markup/Avalonia.Markup/Parsers/SelectorGrammar.cs similarity index 99% rename from src/Markup/Avalonia.Markup.Xaml/Parsers/SelectorGrammar.cs rename to src/Markup/Avalonia.Markup/Parsers/SelectorGrammar.cs index 671fdfff30..014f08d995 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Parsers/SelectorGrammar.cs +++ b/src/Markup/Avalonia.Markup/Parsers/SelectorGrammar.cs @@ -9,7 +9,7 @@ using Sprache; // only reason they have overridden Equals methods is for unit testing. #pragma warning disable 659 -namespace Avalonia.Markup.Xaml.Parsers +namespace Avalonia.Markup.Parsers { internal class SelectorGrammar { diff --git a/src/Markup/Avalonia.Markup.Xaml/Parsers/SelectorParser.cs b/src/Markup/Avalonia.Markup/Parsers/SelectorParser.cs similarity index 99% rename from src/Markup/Avalonia.Markup.Xaml/Parsers/SelectorParser.cs rename to src/Markup/Avalonia.Markup/Parsers/SelectorParser.cs index 1cecb21f17..e50056ddef 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Parsers/SelectorParser.cs +++ b/src/Markup/Avalonia.Markup/Parsers/SelectorParser.cs @@ -7,7 +7,7 @@ using Avalonia.Styling; using Avalonia.Utilities; using Sprache; -namespace Avalonia.Markup.Xaml.Parsers +namespace Avalonia.Markup.Parsers { /// /// Parses a from text. diff --git a/src/Markup/Avalonia.Markup/Properties/AssemblyInfo.cs b/src/Markup/Avalonia.Markup/Properties/AssemblyInfo.cs index 15c0be673a..28f0fd48bd 100644 --- a/src/Markup/Avalonia.Markup/Properties/AssemblyInfo.cs +++ b/src/Markup/Avalonia.Markup/Properties/AssemblyInfo.cs @@ -5,5 +5,5 @@ using System.Reflection; using Avalonia.Metadata; using System.Runtime.CompilerServices; -[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup")] +[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Data")] [assembly: InternalsVisibleTo("Avalonia.Markup.UnitTests")] diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs index 80cd52d529..02fb1f11ad 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs @@ -10,7 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Avalonia.Data; using Avalonia.Logging; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Platform; using Avalonia.Threading; using Avalonia.UnitTests; diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs index 5cc5bae8b0..980cbfaaf8 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs @@ -12,7 +12,7 @@ using Avalonia.Data; using Avalonia.Logging; using Avalonia.Platform; using Avalonia.Threading; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.UnitTests; using Moq; using Xunit; diff --git a/tests/Avalonia.Base.UnitTests/Collections/AvaloniaDictionaryTests.cs b/tests/Avalonia.Base.UnitTests/Collections/AvaloniaDictionaryTests.cs index 0f08c856fe..b6ab7dac34 100644 --- a/tests/Avalonia.Base.UnitTests/Collections/AvaloniaDictionaryTests.cs +++ b/tests/Avalonia.Base.UnitTests/Collections/AvaloniaDictionaryTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using Avalonia.Collections; +using Avalonia.Data.Core; using Xunit; namespace Avalonia.Base.UnitTests.Collections @@ -145,7 +146,7 @@ namespace Avalonia.Base.UnitTests.Collections var tracker = new PropertyChangedTracker(target); target.Clear(); - Assert.Equal(new[] { "Count", "Item[]" }, tracker.Names); + Assert.Equal(new[] { "Count", CommonPropertyNames.IndexerName }, tracker.Names); } } } diff --git a/tests/Avalonia.Markup.UnitTests/Data/BindingExpressionTests.cs b/tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs similarity index 99% rename from tests/Avalonia.Markup.UnitTests/Data/BindingExpressionTests.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs index 2e0f048e21..6b71d28e22 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/BindingExpressionTests.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs @@ -8,12 +8,13 @@ using System.Reactive.Linq; using System.Threading; using System.Threading.Tasks; using Avalonia.Data; -using Avalonia.Markup.Data; +using Avalonia.Data.Converters; +using Avalonia.Data.Core; using Avalonia.UnitTests; using Moq; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class BindingExpressionTests : IClassFixture { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionNodeBuilderTests.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionNodeBuilderTests.cs similarity index 98% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionNodeBuilderTests.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionNodeBuilderTests.cs index 4e583191a5..146b7cace1 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionNodeBuilderTests.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionNodeBuilderTests.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using System.Linq; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionNodeBuilderTests { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionNodeBuilderTests_Errors.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionNodeBuilderTests_Errors.cs similarity index 96% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionNodeBuilderTests_Errors.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionNodeBuilderTests_Errors.cs index ed52d3e2a9..1bf1ce132a 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionNodeBuilderTests_Errors.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionNodeBuilderTests_Errors.cs @@ -1,10 +1,10 @@ // 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. -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionNodeBuilderTests_Errors { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_AttachedProperty.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_AttachedProperty.cs similarity index 98% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_AttachedProperty.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_AttachedProperty.cs index 5ddff63a0c..750e691103 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_AttachedProperty.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_AttachedProperty.cs @@ -6,10 +6,10 @@ using System.Collections.Generic; using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia.Diagnostics; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_AttachedProperty { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_AvaloniaProperty.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_AvaloniaProperty.cs similarity index 97% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_AvaloniaProperty.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_AvaloniaProperty.cs index 6d1e9d94a9..bf2b6cbcb2 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_AvaloniaProperty.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_AvaloniaProperty.cs @@ -6,10 +6,10 @@ using System.Collections.Generic; using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia.Diagnostics; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_AvaloniaProperty { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_DataValidation.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_DataValidation.cs similarity index 99% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_DataValidation.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_DataValidation.cs index 9bf1e4711b..3732569753 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_DataValidation.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_DataValidation.cs @@ -7,11 +7,11 @@ using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; using Avalonia.Data; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_DataValidation : IClassFixture { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Indexer.cs similarity index 99% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Indexer.cs index 1bdbf0d895..8a54f968b1 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Indexer.cs @@ -8,11 +8,11 @@ using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia.Collections; using Avalonia.Diagnostics; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_Indexer { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Lifetime.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Lifetime.cs similarity index 98% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Lifetime.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Lifetime.cs index 04a8e30d16..b88bf2c427 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Lifetime.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Lifetime.cs @@ -7,10 +7,10 @@ using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; using Microsoft.Reactive.Testing; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_Lifetime { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Method.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Method.cs similarity index 97% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Method.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Method.cs index 439e9dc542..ef89c2b4bd 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Method.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Method.cs @@ -1,5 +1,5 @@ using Avalonia.Data; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using System; using System.Collections.Generic; using System.Linq; @@ -8,7 +8,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_Method { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Negation.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Negation.cs similarity index 98% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Negation.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Negation.cs index f4aa85c393..556352f6ca 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Negation.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Negation.cs @@ -5,10 +5,10 @@ using System; using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia.Data; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_Negation { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Observable.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Observable.cs similarity index 98% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Observable.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Observable.cs index aa78c100c1..f1c39617eb 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Observable.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Observable.cs @@ -6,11 +6,11 @@ using System.Collections.Generic; using System.Reactive.Linq; using System.Reactive.Subjects; using Avalonia.Data; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_Observable { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs similarity index 99% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs index 60174e65e6..a3cb11114a 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs @@ -8,12 +8,12 @@ using System.Reactive.Linq; using System.Reactive.Subjects; using Microsoft.Reactive.Testing; using Avalonia.Data; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Avalonia.UnitTests; using Xunit; using System.Threading.Tasks; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_Property { @@ -363,7 +363,7 @@ namespace Avalonia.Markup.UnitTests.Data { "bar", new BindingNotification( - new MissingMemberException("Could not find CLR property 'Bar' on 'Avalonia.Markup.UnitTests.Data.ExpressionObserverTests_Property+WithoutBar'"), + new MissingMemberException("Could not find CLR property 'Bar' on 'Avalonia.Base.UnitTests.Data.Core.ExpressionObserverTests_Property+WithoutBar'"), BindingErrorType.Error), "baz", }, diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_SetValue.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_SetValue.cs similarity index 97% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_SetValue.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_SetValue.cs index 0705ae9c5a..a163229e26 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_SetValue.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_SetValue.cs @@ -4,11 +4,11 @@ using System; using System.Reactive.Linq; using System.Reactive.Subjects; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_SetValue { diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Task.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Task.cs similarity index 98% rename from tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Task.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Task.cs index 87a8be045b..3b9a23f846 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Task.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Task.cs @@ -6,11 +6,11 @@ using System.Collections.Generic; using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia.Data; -using Avalonia.Markup.Data; +using Avalonia.Data.Core; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { public class ExpressionObserverTests_Task { diff --git a/tests/Avalonia.Markup.UnitTests/Data/IndeiBase.cs b/tests/Avalonia.Base.UnitTests/Data/Core/IndeiBase.cs similarity index 96% rename from tests/Avalonia.Markup.UnitTests/Data/IndeiBase.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/IndeiBase.cs index bd0ab71626..6edcdc820d 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/IndeiBase.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/IndeiBase.cs @@ -7,7 +7,7 @@ using System.ComponentModel; using System.Runtime.CompilerServices; using Avalonia.UnitTests; -namespace Avalonia.Markup.UnitTests.Data +namespace Avalonia.Base.UnitTests.Data.Core { internal abstract class IndeiBase : NotifyingBase, INotifyDataErrorInfo { diff --git a/tests/Avalonia.Markup.UnitTests/Data/Plugins/DataAnnotationsValidationPluginTests.cs b/tests/Avalonia.Base.UnitTests/Data/Core/Plugins/DataAnnotationsValidationPluginTests.cs similarity index 99% rename from tests/Avalonia.Markup.UnitTests/Data/Plugins/DataAnnotationsValidationPluginTests.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/Plugins/DataAnnotationsValidationPluginTests.cs index 6663457add..2bffb7b84a 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/Plugins/DataAnnotationsValidationPluginTests.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/Plugins/DataAnnotationsValidationPluginTests.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Avalonia.Data; -using Avalonia.Markup.Data.Plugins; +using Avalonia.Data.Core.Plugins; using Avalonia.UnitTests; using Xunit; diff --git a/tests/Avalonia.Markup.UnitTests/Data/Plugins/ExceptionValidationPluginTests.cs b/tests/Avalonia.Base.UnitTests/Data/Core/Plugins/ExceptionValidationPluginTests.cs similarity index 96% rename from tests/Avalonia.Markup.UnitTests/Data/Plugins/ExceptionValidationPluginTests.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/Plugins/ExceptionValidationPluginTests.cs index eb529a3b13..2a307f9a61 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/Plugins/ExceptionValidationPluginTests.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/Plugins/ExceptionValidationPluginTests.cs @@ -5,11 +5,11 @@ using System; using System.Collections.Generic; using System.Reactive.Linq; using Avalonia.Data; -using Avalonia.Markup.Data.Plugins; +using Avalonia.Data.Core.Plugins; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.UnitTests.Data.Plugins +namespace Avalonia.Base.UnitTests.Data.Core.Plugins { public class ExceptionValidationPluginTests { diff --git a/tests/Avalonia.Markup.UnitTests/Data/Plugins/IndeiValidationPluginTests.cs b/tests/Avalonia.Base.UnitTests/Data/Core/Plugins/IndeiValidationPluginTests.cs similarity index 98% rename from tests/Avalonia.Markup.UnitTests/Data/Plugins/IndeiValidationPluginTests.cs rename to tests/Avalonia.Base.UnitTests/Data/Core/Plugins/IndeiValidationPluginTests.cs index 788bc25a34..45c084014b 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/Plugins/IndeiValidationPluginTests.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/Plugins/IndeiValidationPluginTests.cs @@ -6,10 +6,10 @@ using System.Collections; using System.Collections.Generic; using System.Reactive.Linq; using Avalonia.Data; -using Avalonia.Markup.Data.Plugins; +using Avalonia.Data.Core.Plugins; using Xunit; -namespace Avalonia.Markup.UnitTests.Data.Plugins +namespace Avalonia.Base.UnitTests.Data.Core.Plugins { public class IndeiValidationPluginTests { diff --git a/tests/Avalonia.Markup.UnitTests/DefaultValueConverterTests.cs b/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs similarity index 98% rename from tests/Avalonia.Markup.UnitTests/DefaultValueConverterTests.cs rename to tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs index 0aa2e00c0f..eeb502d730 100644 --- a/tests/Avalonia.Markup.UnitTests/DefaultValueConverterTests.cs +++ b/tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs @@ -7,8 +7,9 @@ using Avalonia.Data; using Xunit; using System.Windows.Input; using System; +using Avalonia.Data.Converters; -namespace Avalonia.Markup.UnitTests +namespace Avalonia.Base.UnitTests.Data.Converters { public class DefaultValueConverterTests { diff --git a/tests/Avalonia.Markup.UnitTests/UnitTestSynchronizationContext.cs b/tests/Avalonia.Base.UnitTests/Data/UnitTestSynchronizationContext.cs similarity index 98% rename from tests/Avalonia.Markup.UnitTests/UnitTestSynchronizationContext.cs rename to tests/Avalonia.Base.UnitTests/Data/UnitTestSynchronizationContext.cs index b5068c511d..838aee6528 100644 --- a/tests/Avalonia.Markup.UnitTests/UnitTestSynchronizationContext.cs +++ b/tests/Avalonia.Base.UnitTests/Data/UnitTestSynchronizationContext.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Reactive.Disposables; using System.Threading; -namespace Avalonia.Markup.UnitTests +namespace Avalonia.Base.UnitTests.Data { internal sealed class UnitTestSynchronizationContext : SynchronizationContext { diff --git a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs index f9da2ab6f3..b10929cbdc 100644 --- a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs @@ -10,7 +10,7 @@ using Avalonia.Controls.Primitives; using Avalonia.Controls.Presenters; using Avalonia.Controls.Templates; using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Platform; using Avalonia.Threading; using Avalonia.UnitTests; diff --git a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs index 71bf9104f7..a194da98a8 100644 --- a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs @@ -1,6 +1,6 @@ using System; using System.Windows.Input; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Xunit; namespace Avalonia.Controls.UnitTests diff --git a/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs b/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs index 653ab17b63..c17893604c 100644 --- a/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs @@ -12,7 +12,7 @@ using Avalonia.Styling; using Avalonia.UnitTests; using Avalonia.VisualTree; using Xunit; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Data; using System.Collections.Generic; diff --git a/tests/Avalonia.Controls.UnitTests/DatePickerTests.cs b/tests/Avalonia.Controls.UnitTests/DatePickerTests.cs index fe4f1ea06e..936d700ad0 100644 --- a/tests/Avalonia.Controls.UnitTests/DatePickerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/DatePickerTests.cs @@ -10,7 +10,7 @@ using Avalonia.Controls.Primitives; using Avalonia.Controls.Presenters; using Avalonia.Controls.Templates; using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Platform; using Avalonia.UnitTests; using Moq; diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs index fee4994ee3..70d59e82c8 100644 --- a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs +++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs @@ -9,7 +9,7 @@ using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Input; using Avalonia.LogicalTree; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Styling; using Avalonia.VisualTree; using Xunit; diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs index 2dfb30a9f0..42578c61ac 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs @@ -6,7 +6,7 @@ using System.ComponentModel; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Styling; using Xunit; diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs index a60074fa43..0f742f5a35 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs @@ -10,7 +10,7 @@ using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.UnitTests; using Xunit; diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs index 642f594e4d..3c6b278e07 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs @@ -10,7 +10,7 @@ using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Xunit; namespace Avalonia.Controls.UnitTests.Primitives diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/ToggleButtonTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/ToggleButtonTests.cs index db60d05a34..377f861668 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/ToggleButtonTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/ToggleButtonTests.cs @@ -1,4 +1,4 @@ -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.UnitTests; using Xunit; diff --git a/tests/Avalonia.Controls.UnitTests/RadioButtonTests.cs b/tests/Avalonia.Controls.UnitTests/RadioButtonTests.cs index 37fb52beeb..2d9dca93f5 100644 --- a/tests/Avalonia.Controls.UnitTests/RadioButtonTests.cs +++ b/tests/Avalonia.Controls.UnitTests/RadioButtonTests.cs @@ -1,4 +1,4 @@ -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.UnitTests; using Xunit; diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index 5ddc8e71e7..af461f07a4 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -8,7 +8,7 @@ using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Input; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Media; using Avalonia.Platform; using Avalonia.UnitTests; diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs index 851d741eae..4d79dd557e 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs @@ -9,7 +9,7 @@ using System.Linq; using Avalonia.Controls.Presenters; using Avalonia.Controls.Templates; using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Platform; using Avalonia.UnitTests; using Moq; diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index 625d9eb26e..a7263cacbd 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -8,6 +8,7 @@ using Avalonia.Collections; using Avalonia.Controls.Presenters; using Avalonia.Controls.Templates; using Avalonia.Data; +using Avalonia.Data.Core; using Avalonia.Input; using Avalonia.LogicalTree; using Avalonia.Markup.Data; diff --git a/tests/Avalonia.LeakTests/ControlTests.cs b/tests/Avalonia.LeakTests/ControlTests.cs index fe3ad59bb4..f00dd6d5d0 100644 --- a/tests/Avalonia.LeakTests/ControlTests.cs +++ b/tests/Avalonia.LeakTests/ControlTests.cs @@ -185,7 +185,7 @@ namespace Avalonia.LeakTests Content = new TextBox() }; - var binding = new Avalonia.Markup.Xaml.Data.Binding + var binding = new Avalonia.Markup.Data.Binding { Path = "Name" }; diff --git a/tests/Avalonia.LeakTests/ExpressionObserverTests.cs b/tests/Avalonia.LeakTests/ExpressionObserverTests.cs index d0f892bebb..96f9e37897 100644 --- a/tests/Avalonia.LeakTests/ExpressionObserverTests.cs +++ b/tests/Avalonia.LeakTests/ExpressionObserverTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Avalonia.Collections; +using Avalonia.Data.Core; using Avalonia.Markup.Data; using Avalonia.UnitTests; using JetBrains.dotMemoryUnit; diff --git a/tests/Avalonia.Markup.UnitTests/Data/BindingTests.cs b/tests/Avalonia.Markup.UnitTests/Data/BindingTests.cs new file mode 100644 index 0000000000..6c95a465b3 --- /dev/null +++ b/tests/Avalonia.Markup.UnitTests/Data/BindingTests.cs @@ -0,0 +1,548 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using Avalonia.Controls; +using Avalonia.Data; +using Avalonia.Markup.Data; +using Moq; +using Xunit; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using Avalonia.UnitTests; +using Avalonia.Data.Converters; +using Avalonia.Data.Core; + +namespace Avalonia.Markup.UnitTests.Data +{ + public class BindingTests + { + [Fact] + public void OneWay_Binding_Should_Be_Set_Up() + { + var source = new Source { Foo = "foo" }; + var target = new TextBlock { DataContext = source }; + var binding = new Binding + { + Path = "Foo", + Mode = BindingMode.OneWay, + }; + + target.Bind(TextBox.TextProperty, binding); + + Assert.Equal("foo", target.Text); + source.Foo = "bar"; + Assert.Equal("bar", target.Text); + target.Text = "baz"; + Assert.Equal("bar", source.Foo); + } + + [Fact] + public void TwoWay_Binding_Should_Be_Set_Up() + { + var source = new Source { Foo = "foo" }; + var target = new TextBlock { DataContext = source }; + var binding = new Binding + { + Path = "Foo", + Mode = BindingMode.TwoWay, + }; + + target.Bind(TextBox.TextProperty, binding); + + Assert.Equal("foo", target.Text); + source.Foo = "bar"; + Assert.Equal("bar", target.Text); + target.Text = "baz"; + Assert.Equal("baz", source.Foo); + } + + [Fact] + public void OneTime_Binding_Should_Be_Set_Up() + { + var source = new Source { Foo = "foo" }; + var target = new TextBlock { DataContext = source }; + var binding = new Binding + { + Path = "Foo", + Mode = BindingMode.OneTime, + }; + + target.Bind(TextBox.TextProperty, binding); + + Assert.Equal("foo", target.Text); + source.Foo = "bar"; + Assert.Equal("foo", target.Text); + target.Text = "baz"; + Assert.Equal("bar", source.Foo); + } + + [Fact] + public void OneWayToSource_Binding_Should_Be_Set_Up() + { + var source = new Source { Foo = "foo" }; + var target = new TextBlock { DataContext = source, Text = "bar" }; + var binding = new Binding + { + Path = "Foo", + Mode = BindingMode.OneWayToSource, + }; + + target.Bind(TextBox.TextProperty, binding); + + Assert.Equal("bar", source.Foo); + target.Text = "baz"; + Assert.Equal("baz", source.Foo); + source.Foo = "quz"; + Assert.Equal("baz", target.Text); + } + + [Fact] + public void Default_BindingMode_Should_Be_Used() + { + var source = new Source { Foo = "foo" }; + var target = new TwoWayBindingTest { DataContext = source }; + var binding = new Binding + { + Path = "Foo", + }; + + target.Bind(TwoWayBindingTest.TwoWayProperty, binding); + + Assert.Equal("foo", target.TwoWay); + source.Foo = "bar"; + Assert.Equal("bar", target.TwoWay); + target.TwoWay = "baz"; + Assert.Equal("baz", source.Foo); + } + + [Fact] + public void DataContext_Binding_Should_Use_Parent_DataContext() + { + var parentDataContext = Mock.Of(x => x.Header == (object)"Foo"); + + var parent = new Decorator + { + Child = new Control(), + DataContext = parentDataContext, + }; + + var binding = new Binding + { + Path = "Header", + }; + + parent.Child.Bind(Control.DataContextProperty, binding); + + Assert.Equal("Foo", parent.Child.DataContext); + + parentDataContext = Mock.Of(x => x.Header == (object)"Bar"); + parent.DataContext = parentDataContext; + Assert.Equal("Bar", parent.Child.DataContext); + } + + [Fact] + public void DataContext_Binding_Should_Track_Parent() + { + var parent = new Decorator + { + DataContext = new { Foo = "foo" }, + }; + + var child = new Control(); + + var binding = new Binding + { + Path = "Foo", + }; + + child.Bind(Control.DataContextProperty, binding); + + Assert.Null(child.DataContext); + parent.Child = child; + Assert.Equal("foo", child.DataContext); + } + + [Fact] + public void DataContext_Binding_Should_Produce_Correct_Results() + { + var viewModel = new { Foo = "bar" }; + var root = new Decorator + { + DataContext = viewModel, + }; + + var child = new Control(); + var values = new List(); + + child.GetObservable(Control.DataContextProperty).Subscribe(x => values.Add(x)); + child.Bind(Control.DataContextProperty, new Binding("Foo")); + + // When binding to DataContext and the target isn't found, the binding should produce + // null rather than UnsetValue in order to not propagate incorrect DataContexts from + // parent controls while things are being set up. This logic is implemented in + // `Avalonia.Markup.Xaml.Binding.Initiate`. + Assert.True(child.IsSet(Control.DataContextProperty)); + + root.Child = child; + + Assert.Equal(new[] { null, "bar" }, values); + } + + [Fact] + public void Should_Use_DefaultValueConverter_When_No_Converter_Specified() + { + var target = new TextBlock(); ; + var binding = new Binding + { + Path = "Foo", + }; + + var result = binding.Initiate(target, TextBox.TextProperty).Subject; + + Assert.IsType(((BindingExpression)result).Converter); + } + + [Fact] + public void Should_Use_Supplied_Converter() + { + var target = new TextBlock(); + var converter = new Mock(); + var binding = new Binding + { + Converter = converter.Object, + Path = "Foo", + }; + + var result = binding.Initiate(target, TextBox.TextProperty).Subject; + + Assert.Same(converter.Object, ((BindingExpression)result).Converter); + } + + [Fact] + public void Should_Pass_ConverterParameter_To_Supplied_Converter() + { + var target = new TextBlock(); + var converter = new Mock(); + var binding = new Binding + { + Converter = converter.Object, + ConverterParameter = "foo", + Path = "Bar", + }; + + var result = binding.Initiate(target, TextBox.TextProperty).Subject; + + Assert.Same("foo", ((BindingExpression)result).ConverterParameter); + } + + [Fact] + public void Should_Return_FallbackValue_When_Path_Not_Resolved() + { + var target = new TextBlock(); + var source = new Source(); + var binding = new Binding + { + Source = source, + Path = "BadPath", + FallbackValue = "foofallback", + }; + + target.Bind(TextBlock.TextProperty, binding); + + Assert.Equal("foofallback", target.Text); + } + + [Fact] + public void Should_Return_FallbackValue_When_Invalid_Source_Type() + { + var target = new ProgressBar(); + var source = new Source { Foo = "foo" }; + var binding = new Binding + { + Source = source, + Path = "Foo", + FallbackValue = 42, + }; + + target.Bind(ProgressBar.ValueProperty, binding); + + Assert.Equal(42, target.Value); + } + + /// + /// Tests a problem discovered with ListBox with selection. + /// + /// + /// - Items is bound to DataContext first, followed by say SelectedIndex + /// - When the ListBox is removed from the logical tree, DataContext becomes null (as it's + /// inherited) + /// - This changes Items to null, which changes SelectedIndex to null as there are no + /// longer any items + /// - However, the news that DataContext is now null hasn't yet reached the SelectedIndex + /// binding and so the unselection is sent back to the ViewModel + /// + [Fact] + public void Should_Not_Write_To_Old_DataContext() + { + var vm = new OldDataContextViewModel(); + var target = new OldDataContextTest(); + + var fooBinding = new Binding + { + Path = "Foo", + Mode = BindingMode.TwoWay, + }; + + var barBinding = new Binding + { + Path = "Bar", + Mode = BindingMode.TwoWay, + }; + + // Bind Foo and Bar to the VM. + target.Bind(OldDataContextTest.FooProperty, fooBinding); + target.Bind(OldDataContextTest.BarProperty, barBinding); + target.DataContext = vm; + + // Make sure the control's Foo and Bar properties are read from the VM + Assert.Equal(1, target.GetValue(OldDataContextTest.FooProperty)); + Assert.Equal(2, target.GetValue(OldDataContextTest.BarProperty)); + + // Set DataContext to null. + target.DataContext = null; + + // Foo and Bar are no longer bound so they return 0, their default value. + Assert.Equal(0, target.GetValue(OldDataContextTest.FooProperty)); + Assert.Equal(0, target.GetValue(OldDataContextTest.BarProperty)); + + // The problem was here - DataContext is now null, setting Foo to 0. Bar is bound to + // Foo so Bar also gets set to 0. However the Bar binding still had a reference to + // the VM and so vm.Bar was set to 0 erroneously. + Assert.Equal(1, vm.Foo); + Assert.Equal(2, vm.Bar); + } + + [Fact] + public void AvaloniaObject_this_Operator_Accepts_Binding() + { + var target = new ContentControl + { + DataContext = new { Foo = "foo" } + }; + + target[!ContentControl.ContentProperty] = new Binding("Foo"); + + Assert.Equal("foo", target.Content); + } + + [Fact] + public void StyledProperty_SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values() + { + var viewModel = new TestStackOverflowViewModel() + { + Value = 50 + }; + + var target = new StyledPropertyClass(); + + target.Bind(StyledPropertyClass.DoubleValueProperty, + new Binding("Value") { Mode = BindingMode.TwoWay, Source = viewModel }); + + var child = new StyledPropertyClass(); + + child.Bind(StyledPropertyClass.DoubleValueProperty, + new Binding("DoubleValue") + { + Mode = BindingMode.TwoWay, + Source = target + }); + + Assert.Equal(1, viewModel.SetterInvokedCount); + + //here in real life stack overflow exception is thrown issue #855 and #824 + target.DoubleValue = 51.001; + + Assert.Equal(2, viewModel.SetterInvokedCount); + + double expected = 51; + + Assert.Equal(expected, viewModel.Value); + Assert.Equal(expected, target.DoubleValue); + Assert.Equal(expected, child.DoubleValue); + } + + [Fact] + public void SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values() + { + var viewModel = new TestStackOverflowViewModel() + { + Value = 50 + }; + + var target = new DirectPropertyClass(); + + target.Bind(DirectPropertyClass.DoubleValueProperty, new Binding("Value") + { + Mode = BindingMode.TwoWay, + Source = viewModel + }); + + var child = new DirectPropertyClass(); + + child.Bind(DirectPropertyClass.DoubleValueProperty, + new Binding("DoubleValue") + { + Mode = BindingMode.TwoWay, + Source = target + }); + + Assert.Equal(1, viewModel.SetterInvokedCount); + + //here in real life stack overflow exception is thrown issue #855 and #824 + target.DoubleValue = 51.001; + + Assert.Equal(2, viewModel.SetterInvokedCount); + + double expected = 51; + + Assert.Equal(expected, viewModel.Value); + Assert.Equal(expected, target.DoubleValue); + Assert.Equal(expected, child.DoubleValue); + } + + private class StyledPropertyClass : AvaloniaObject + { + public static readonly StyledProperty DoubleValueProperty = + AvaloniaProperty.Register(nameof(DoubleValue)); + + public double DoubleValue + { + get { return GetValue(DoubleValueProperty); } + set { SetValue(DoubleValueProperty, value); } + } + } + + private class DirectPropertyClass : AvaloniaObject + { + public static readonly DirectProperty DoubleValueProperty = + AvaloniaProperty.RegisterDirect( + nameof(DoubleValue), + o => o.DoubleValue, + (o, v) => o.DoubleValue = v); + + private double _doubleValue; + public double DoubleValue + { + get { return _doubleValue; } + set { SetAndRaise(DoubleValueProperty, ref _doubleValue, value); } + } + } + + private class TestStackOverflowViewModel : INotifyPropertyChanged + { + public int SetterInvokedCount { get; private set; } + + public const int MaxInvokedCount = 1000; + + private double _value; + + public event PropertyChangedEventHandler PropertyChanged; + + public double Value + { + get { return _value; } + set + { + if (_value != value) + { + SetterInvokedCount++; + if (SetterInvokedCount < MaxInvokedCount) + { + _value = (int)value; + if (_value > 75) _value = 75; + if (_value < 25) _value = 25; + } + else + { + _value = value; + } + + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value))); + } + } + } + } + + private class TwoWayBindingTest : Control + { + public static readonly StyledProperty TwoWayProperty = + AvaloniaProperty.Register( + "TwoWay", + defaultBindingMode: BindingMode.TwoWay); + + public string TwoWay + { + get { return GetValue(TwoWayProperty); } + set { SetValue(TwoWayProperty, value); } + } + } + + public class Source : INotifyPropertyChanged + { + private string _foo; + + public string Foo + { + get { return _foo; } + set + { + _foo = value; + RaisePropertyChanged(); + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + private void RaisePropertyChanged([CallerMemberName] string prop = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); + } + } + + private class OldDataContextViewModel + { + public int Foo { get; set; } = 1; + public int Bar { get; set; } = 2; + } + + private class OldDataContextTest : Control + { + public static readonly StyledProperty FooProperty = + AvaloniaProperty.Register("Foo"); + + public static readonly StyledProperty BarProperty = + AvaloniaProperty.Register("Bar"); + + public OldDataContextTest() + { + Bind(BarProperty, this.GetObservable(FooProperty)); + } + } + + private class InheritanceTest : Decorator + { + public static readonly StyledProperty BazProperty = + AvaloniaProperty.Register(nameof(Baz), defaultValue: 6, inherits: true); + + public int Baz + { + get { return GetValue(BazProperty); } + set { SetValue(BazProperty, value); } + } + } + } +} diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_DataValidation.cs b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_DataValidation.cs similarity index 96% rename from tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_DataValidation.cs rename to tests/Avalonia.Markup.UnitTests/Data/BindingTests_DataValidation.cs index 5dd8d0cdf9..04b91b5f6a 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_DataValidation.cs +++ b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_DataValidation.cs @@ -5,11 +5,11 @@ using System; using System.Reactive.Linq; using Avalonia.Controls; using Avalonia.Data; +using Avalonia.Data.Core; using Avalonia.Markup.Data; -using Avalonia.Markup.Xaml.Data; using Xunit; -namespace Avalonia.Markup.Xaml.UnitTests.Data +namespace Avalonia.Markup.UnitTests.Data { public class BindingTests_DataValidation { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_ElementName.cs b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_ElementName.cs similarity index 98% rename from tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_ElementName.cs rename to tests/Avalonia.Markup.UnitTests/Data/BindingTests_ElementName.cs index d582964987..a05b121a42 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_ElementName.cs +++ b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_ElementName.cs @@ -2,11 +2,11 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia.Controls; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.Xaml.UnitTests.Data +namespace Avalonia.Markup.UnitTests.Data { public class BindingTests_ElementName { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_RelativeSource.cs b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_RelativeSource.cs similarity index 98% rename from tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_RelativeSource.cs rename to tests/Avalonia.Markup.UnitTests/Data/BindingTests_RelativeSource.cs index c46fb6fce2..36e801d22d 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_RelativeSource.cs +++ b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_RelativeSource.cs @@ -2,11 +2,11 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia.Controls; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.Xaml.UnitTests.Data +namespace Avalonia.Markup.UnitTests.Data { public class BindingTests_RelativeSource { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Self.cs b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_Self.cs similarity index 96% rename from tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Self.cs rename to tests/Avalonia.Markup.UnitTests/Data/BindingTests_Self.cs index e0d16a9563..7b899472bb 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Self.cs +++ b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_Self.cs @@ -5,12 +5,12 @@ using System; using Moq; using Avalonia.Controls; using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; using Avalonia.Styling; using Xunit; using System.Reactive.Disposables; +using Avalonia.Markup.Data; -namespace Avalonia.Markup.Xaml.UnitTests.Data +namespace Avalonia.Markup.UnitTests.Data { public class BindingTests_Self { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Source.cs b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_Source.cs similarity index 94% rename from tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Source.cs rename to tests/Avalonia.Markup.UnitTests/Data/BindingTests_Source.cs index 1fbf8b679d..9cc02539ce 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Source.cs +++ b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_Source.cs @@ -5,12 +5,11 @@ using Moq; using Avalonia.Controls; using Avalonia.Data; using Avalonia.Markup.Data; -using Avalonia.Markup.Xaml.Data; using Xunit; using System.ComponentModel; using System.Runtime.CompilerServices; -namespace Avalonia.Markup.Xaml.UnitTests.Data +namespace Avalonia.Markup.UnitTests.Data { public class BindingTests_Source { diff --git a/tests/Avalonia.Markup.UnitTests/Data/BindingTests_TemplatedParent.cs b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_TemplatedParent.cs new file mode 100644 index 0000000000..e9c3da5160 --- /dev/null +++ b/tests/Avalonia.Markup.UnitTests/Data/BindingTests_TemplatedParent.cs @@ -0,0 +1,76 @@ +// 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. + +using System; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Moq; +using Avalonia.Controls; +using Avalonia.Data; +using Avalonia.Styling; +using Xunit; +using System.Reactive.Disposables; +using Avalonia.UnitTests; +using Avalonia.VisualTree; +using System.Linq; +using Avalonia.Markup.Data; + +namespace Avalonia.Markup.UnitTests.Data +{ + public class BindingTests_TemplatedParent + { + [Fact] + public void OneWay_Binding_Should_Be_Set_Up() + { + var target = CreateTarget(); + var binding = new Binding + { + Mode = BindingMode.OneWay, + RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent), + Priority = BindingPriority.TemplatedParent, + Path = "Foo", + }; + + target.Object.Bind(TextBox.TextProperty, binding); + + target.Verify(x => x.Bind( + TextBox.TextProperty, + It.IsAny>(), + BindingPriority.TemplatedParent)); + } + + [Fact] + public void TwoWay_Binding_Should_Be_Set_Up() + { + var target = CreateTarget(); + var binding = new Binding + { + Mode = BindingMode.TwoWay, + RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent), + Priority = BindingPriority.TemplatedParent, + Path = "Foo", + }; + + target.Object.Bind(TextBox.TextProperty, binding); + + target.Verify(x => x.Bind( + TextBox.TextProperty, + It.IsAny>(), + BindingPriority.TemplatedParent)); + } + + private Mock CreateTarget( + ITemplatedControl templatedParent = null, + string text = null) + { + var result = new Mock(); + + result.Setup(x => x.GetValue(Control.TemplatedParentProperty)).Returns(templatedParent); + result.Setup(x => x.GetValue((AvaloniaProperty)Control.TemplatedParentProperty)).Returns(templatedParent); + result.Setup(x => x.GetValue((AvaloniaProperty)TextBox.TextProperty)).Returns(text); + result.Setup(x => x.Bind(It.IsAny(), It.IsAny>(), It.IsAny())) + .Returns(Disposable.Empty); + return result; + } + } +} diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/MultiBindingTests.cs b/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs similarity index 96% rename from tests/Avalonia.Markup.Xaml.UnitTests/Data/MultiBindingTests.cs rename to tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs index 4450cc0c90..b341af2810 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/MultiBindingTests.cs +++ b/tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests.cs @@ -8,11 +8,12 @@ using System.Linq; using System.Reactive.Linq; using Moq; using Avalonia.Controls; -using Avalonia.Markup.Xaml.Data; using Xunit; using System.Threading.Tasks; +using Avalonia.Data.Converters; +using Avalonia.Markup.Data; -namespace Avalonia.Markup.Xaml.UnitTests.Data +namespace Avalonia.Markup.UnitTests.Data { public class MultiBindingTests { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Parsers/SelectorGrammarTests.cs b/tests/Avalonia.Markup.UnitTests/Parsers/SelectorGrammarTests.cs similarity index 98% rename from tests/Avalonia.Markup.Xaml.UnitTests/Parsers/SelectorGrammarTests.cs rename to tests/Avalonia.Markup.UnitTests/Parsers/SelectorGrammarTests.cs index ad2c1bf8d3..8cb2639125 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Parsers/SelectorGrammarTests.cs +++ b/tests/Avalonia.Markup.UnitTests/Parsers/SelectorGrammarTests.cs @@ -2,11 +2,11 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System.Linq; -using Avalonia.Markup.Xaml.Parsers; +using Avalonia.Markup.Parsers; using Sprache; using Xunit; -namespace Avalonia.Xaml.Base.UnitTest.Parsers +namespace Avalonia.Markup.UnitTest.Parsers { public class SelectorGrammarTests { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Parsers/SelectorParserTests.cs b/tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs similarity index 91% rename from tests/Avalonia.Markup.Xaml.UnitTests/Parsers/SelectorParserTests.cs rename to tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs index 8c0b043907..360be7f909 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Parsers/SelectorParserTests.cs +++ b/tests/Avalonia.Markup.UnitTests/Parsers/SelectorParserTests.cs @@ -1,6 +1,6 @@ using System; using Avalonia.Controls; -using Avalonia.Markup.Xaml.Parsers; +using Avalonia.Markup.Parsers; using Xunit; namespace Avalonia.Markup.Xaml.UnitTests.Parsers diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs index c6f89e07a6..0a00b9d39d 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs @@ -8,475 +8,18 @@ using System.Reactive.Linq; using Avalonia.Controls; using Avalonia.Data; using Avalonia.Markup.Data; -using Avalonia.Markup.Xaml.Data; using Moq; using Xunit; using System.ComponentModel; using System.Runtime.CompilerServices; using Avalonia.UnitTests; +using Avalonia.Data.Converters; +using Avalonia.Data.Core; namespace Avalonia.Markup.Xaml.UnitTests.Data { public class BindingTests { - [Fact] - public void OneWay_Binding_Should_Be_Set_Up() - { - var source = new Source { Foo = "foo" }; - var target = new TextBlock { DataContext = source }; - var binding = new Binding - { - Path = "Foo", - Mode = BindingMode.OneWay, - }; - - target.Bind(TextBox.TextProperty, binding); - - Assert.Equal("foo", target.Text); - source.Foo = "bar"; - Assert.Equal("bar", target.Text); - target.Text = "baz"; - Assert.Equal("bar", source.Foo); - } - - [Fact] - public void TwoWay_Binding_Should_Be_Set_Up() - { - var source = new Source { Foo = "foo" }; - var target = new TextBlock { DataContext = source }; - var binding = new Binding - { - Path = "Foo", - Mode = BindingMode.TwoWay, - }; - - target.Bind(TextBox.TextProperty, binding); - - Assert.Equal("foo", target.Text); - source.Foo = "bar"; - Assert.Equal("bar", target.Text); - target.Text = "baz"; - Assert.Equal("baz", source.Foo); - } - - [Fact] - public void OneTime_Binding_Should_Be_Set_Up() - { - var source = new Source { Foo = "foo" }; - var target = new TextBlock { DataContext = source }; - var binding = new Binding - { - Path = "Foo", - Mode = BindingMode.OneTime, - }; - - target.Bind(TextBox.TextProperty, binding); - - Assert.Equal("foo", target.Text); - source.Foo = "bar"; - Assert.Equal("foo", target.Text); - target.Text = "baz"; - Assert.Equal("bar", source.Foo); - } - - [Fact] - public void OneWayToSource_Binding_Should_Be_Set_Up() - { - var source = new Source { Foo = "foo" }; - var target = new TextBlock { DataContext = source, Text = "bar" }; - var binding = new Binding - { - Path = "Foo", - Mode = BindingMode.OneWayToSource, - }; - - target.Bind(TextBox.TextProperty, binding); - - Assert.Equal("bar", source.Foo); - target.Text = "baz"; - Assert.Equal("baz", source.Foo); - source.Foo = "quz"; - Assert.Equal("baz", target.Text); - } - - [Fact] - public void Default_BindingMode_Should_Be_Used() - { - var source = new Source { Foo = "foo" }; - var target = new TwoWayBindingTest { DataContext = source }; - var binding = new Binding - { - Path = "Foo", - }; - - target.Bind(TwoWayBindingTest.TwoWayProperty, binding); - - Assert.Equal("foo", target.TwoWay); - source.Foo = "bar"; - Assert.Equal("bar", target.TwoWay); - target.TwoWay = "baz"; - Assert.Equal("baz", source.Foo); - } - - [Fact] - public void DataContext_Binding_Should_Use_Parent_DataContext() - { - var parentDataContext = Mock.Of(x => x.Header == (object)"Foo"); - - var parent = new Decorator - { - Child = new Control(), - DataContext = parentDataContext, - }; - - var binding = new Binding - { - Path = "Header", - }; - - parent.Child.Bind(Control.DataContextProperty, binding); - - Assert.Equal("Foo", parent.Child.DataContext); - - parentDataContext = Mock.Of(x => x.Header == (object)"Bar"); - parent.DataContext = parentDataContext; - Assert.Equal("Bar", parent.Child.DataContext); - } - - [Fact] - public void DataContext_Binding_Should_Track_Parent() - { - var parent = new Decorator - { - DataContext = new { Foo = "foo" }, - }; - - var child = new Control(); - - var binding = new Binding - { - Path = "Foo", - }; - - child.Bind(Control.DataContextProperty, binding); - - Assert.Null(child.DataContext); - parent.Child = child; - Assert.Equal("foo", child.DataContext); - } - - [Fact] - public void DataContext_Binding_Should_Produce_Correct_Results() - { - var viewModel = new { Foo = "bar" }; - var root = new Decorator - { - DataContext = viewModel, - }; - - var child = new Control(); - var values = new List(); - - child.GetObservable(Control.DataContextProperty).Subscribe(x => values.Add(x)); - child.Bind(Control.DataContextProperty, new Binding("Foo")); - - // When binding to DataContext and the target isn't found, the binding should produce - // null rather than UnsetValue in order to not propagate incorrect DataContexts from - // parent controls while things are being set up. This logic is implemented in - // `Avalonia.Markup.Xaml.Binding.Initiate`. - Assert.True(child.IsSet(Control.DataContextProperty)); - - root.Child = child; - - Assert.Equal(new[] { null, "bar" }, values); - } - - [Fact] - public void Should_Use_DefaultValueConverter_When_No_Converter_Specified() - { - var target = new TextBlock(); ; - var binding = new Binding - { - Path = "Foo", - }; - - var result = binding.Initiate(target, TextBox.TextProperty).Subject; - - Assert.IsType(((BindingExpression)result).Converter); - } - - [Fact] - public void Should_Use_Supplied_Converter() - { - var target = new TextBlock(); - var converter = new Mock(); - var binding = new Binding - { - Converter = converter.Object, - Path = "Foo", - }; - - var result = binding.Initiate(target, TextBox.TextProperty).Subject; - - Assert.Same(converter.Object, ((BindingExpression)result).Converter); - } - - [Fact] - public void Should_Pass_ConverterParameter_To_Supplied_Converter() - { - var target = new TextBlock(); - var converter = new Mock(); - var binding = new Binding - { - Converter = converter.Object, - ConverterParameter = "foo", - Path = "Bar", - }; - - var result = binding.Initiate(target, TextBox.TextProperty).Subject; - - Assert.Same("foo", ((BindingExpression)result).ConverterParameter); - } - - [Fact] - public void Should_Return_FallbackValue_When_Path_Not_Resolved() - { - var target = new TextBlock(); - var source = new Source(); - var binding = new Binding - { - Source = source, - Path = "BadPath", - FallbackValue = "foofallback", - }; - - target.Bind(TextBlock.TextProperty, binding); - - Assert.Equal("foofallback", target.Text); - } - - [Fact] - public void Should_Return_FallbackValue_When_Invalid_Source_Type() - { - var target = new ProgressBar(); - var source = new Source { Foo = "foo" }; - var binding = new Binding - { - Source = source, - Path = "Foo", - FallbackValue = 42, - }; - - target.Bind(ProgressBar.ValueProperty, binding); - - Assert.Equal(42, target.Value); - } - - /// - /// Tests a problem discovered with ListBox with selection. - /// - /// - /// - Items is bound to DataContext first, followed by say SelectedIndex - /// - When the ListBox is removed from the logical tree, DataContext becomes null (as it's - /// inherited) - /// - This changes Items to null, which changes SelectedIndex to null as there are no - /// longer any items - /// - However, the news that DataContext is now null hasn't yet reached the SelectedIndex - /// binding and so the unselection is sent back to the ViewModel - /// - [Fact] - public void Should_Not_Write_To_Old_DataContext() - { - var vm = new OldDataContextViewModel(); - var target = new OldDataContextTest(); - - var fooBinding = new Binding - { - Path = "Foo", - Mode = BindingMode.TwoWay, - }; - - var barBinding = new Binding - { - Path = "Bar", - Mode = BindingMode.TwoWay, - }; - - // Bind Foo and Bar to the VM. - target.Bind(OldDataContextTest.FooProperty, fooBinding); - target.Bind(OldDataContextTest.BarProperty, barBinding); - target.DataContext = vm; - - // Make sure the control's Foo and Bar properties are read from the VM - Assert.Equal(1, target.GetValue(OldDataContextTest.FooProperty)); - Assert.Equal(2, target.GetValue(OldDataContextTest.BarProperty)); - - // Set DataContext to null. - target.DataContext = null; - - // Foo and Bar are no longer bound so they return 0, their default value. - Assert.Equal(0, target.GetValue(OldDataContextTest.FooProperty)); - Assert.Equal(0, target.GetValue(OldDataContextTest.BarProperty)); - - // The problem was here - DataContext is now null, setting Foo to 0. Bar is bound to - // Foo so Bar also gets set to 0. However the Bar binding still had a reference to - // the VM and so vm.Bar was set to 0 erroneously. - Assert.Equal(1, vm.Foo); - Assert.Equal(2, vm.Bar); - } - - [Fact] - public void AvaloniaObject_this_Operator_Accepts_Binding() - { - var target = new ContentControl - { - DataContext = new { Foo = "foo" } - }; - - target[!ContentControl.ContentProperty] = new Binding("Foo"); - - Assert.Equal("foo", target.Content); - } - - [Fact] - public void StyledProperty_SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values() - { - var viewModel = new TestStackOverflowViewModel() - { - Value = 50 - }; - - var target = new StyledPropertyClass(); - - target.Bind(StyledPropertyClass.DoubleValueProperty, - new Binding("Value") { Mode = BindingMode.TwoWay, Source = viewModel }); - - var child = new StyledPropertyClass(); - - child.Bind(StyledPropertyClass.DoubleValueProperty, - new Binding("DoubleValue") - { - Mode = BindingMode.TwoWay, - Source = target - }); - - Assert.Equal(1, viewModel.SetterInvokedCount); - - //here in real life stack overflow exception is thrown issue #855 and #824 - target.DoubleValue = 51.001; - - Assert.Equal(2, viewModel.SetterInvokedCount); - - double expected = 51; - - Assert.Equal(expected, viewModel.Value); - Assert.Equal(expected, target.DoubleValue); - Assert.Equal(expected, child.DoubleValue); - } - - [Fact] - public void SetValue_Should_Not_Cause_StackOverflow_And_Have_Correct_Values() - { - var viewModel = new TestStackOverflowViewModel() - { - Value = 50 - }; - - var target = new DirectPropertyClass(); - - target.Bind(DirectPropertyClass.DoubleValueProperty, new Binding("Value") - { - Mode = BindingMode.TwoWay, - Source = viewModel - }); - - var child = new DirectPropertyClass(); - - child.Bind(DirectPropertyClass.DoubleValueProperty, - new Binding("DoubleValue") - { - Mode = BindingMode.TwoWay, - Source = target - }); - - Assert.Equal(1, viewModel.SetterInvokedCount); - - //here in real life stack overflow exception is thrown issue #855 and #824 - target.DoubleValue = 51.001; - - Assert.Equal(2, viewModel.SetterInvokedCount); - - double expected = 51; - - Assert.Equal(expected, viewModel.Value); - Assert.Equal(expected, target.DoubleValue); - Assert.Equal(expected, child.DoubleValue); - } - - private class StyledPropertyClass : AvaloniaObject - { - public static readonly StyledProperty DoubleValueProperty = - AvaloniaProperty.Register(nameof(DoubleValue)); - - public double DoubleValue - { - get { return GetValue(DoubleValueProperty); } - set { SetValue(DoubleValueProperty, value); } - } - } - - private class DirectPropertyClass : AvaloniaObject - { - public static readonly DirectProperty DoubleValueProperty = - AvaloniaProperty.RegisterDirect( - nameof(DoubleValue), - o => o.DoubleValue, - (o, v) => o.DoubleValue = v); - - private double _doubleValue; - public double DoubleValue - { - get { return _doubleValue; } - set { SetAndRaise(DoubleValueProperty, ref _doubleValue, value); } - } - } - - private class TestStackOverflowViewModel : INotifyPropertyChanged - { - public int SetterInvokedCount { get; private set; } - - public const int MaxInvokedCount = 1000; - - private double _value; - - public event PropertyChangedEventHandler PropertyChanged; - - public double Value - { - get { return _value; } - set - { - if (_value != value) - { - SetterInvokedCount++; - if (SetterInvokedCount < MaxInvokedCount) - { - _value = (int)value; - if (_value > 75) _value = 75; - if (_value < 25) _value = 25; - } - else - { - _value = value; - } - - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value))); - } - } - } - } - - [Fact] public void Binding_With_Null_Path_Works() { @@ -484,8 +27,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data { var xaml = @" + xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'> "; var loader = new AvaloniaXamlLoader(); @@ -498,73 +40,5 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data Assert.Equal("foo", textBlock.Text); } } - - private class TwoWayBindingTest : Control - { - public static readonly StyledProperty TwoWayProperty = - AvaloniaProperty.Register( - "TwoWay", - defaultBindingMode: BindingMode.TwoWay); - - public string TwoWay - { - get { return GetValue(TwoWayProperty); } - set { SetValue(TwoWayProperty, value); } - } - } - - public class Source : INotifyPropertyChanged - { - private string _foo; - - public string Foo - { - get { return _foo; } - set - { - _foo = value; - RaisePropertyChanged(); - } - } - - public event PropertyChangedEventHandler PropertyChanged; - - private void RaisePropertyChanged([CallerMemberName] string prop = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); - } - } - - private class OldDataContextViewModel - { - public int Foo { get; set; } = 1; - public int Bar { get; set; } = 2; - } - - private class OldDataContextTest : Control - { - public static readonly StyledProperty FooProperty = - AvaloniaProperty.Register("Foo"); - - public static readonly StyledProperty BarProperty = - AvaloniaProperty.Register("Bar"); - - public OldDataContextTest() - { - Bind(BarProperty, this.GetObservable(FooProperty)); - } - } - - private class InheritanceTest : Decorator - { - public static readonly StyledProperty BazProperty = - AvaloniaProperty.Register(nameof(Baz), defaultValue: 6, inherits: true); - - public int Baz - { - get { return GetValue(BazProperty); } - set { SetValue(BazProperty, value); } - } - } } } diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_TemplatedParent.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_TemplatedParent.cs index ccb13039f1..ab5b7e76a4 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_TemplatedParent.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_TemplatedParent.cs @@ -7,7 +7,6 @@ using System.Reactive.Subjects; using Moq; using Avalonia.Controls; using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; using Avalonia.Styling; using Xunit; using System.Reactive.Disposables; @@ -19,46 +18,6 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data { public class BindingTests_TemplatedParent { - [Fact] - public void OneWay_Binding_Should_Be_Set_Up() - { - var target = CreateTarget(); - var binding = new Binding - { - Mode = BindingMode.OneWay, - RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent), - Priority = BindingPriority.TemplatedParent, - Path = "Foo", - }; - - target.Object.Bind(TextBox.TextProperty, binding); - - target.Verify(x => x.Bind( - TextBox.TextProperty, - It.IsAny>(), - BindingPriority.TemplatedParent)); - } - - [Fact] - public void TwoWay_Binding_Should_Be_Set_Up() - { - var target = CreateTarget(); - var binding = new Binding - { - Mode = BindingMode.TwoWay, - RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent), - Priority = BindingPriority.TemplatedParent, - Path = "Foo", - }; - - target.Object.Bind(TextBox.TextProperty, binding); - - target.Verify(x => x.Bind( - TextBox.TextProperty, - It.IsAny>(), - BindingPriority.TemplatedParent)); - } - [Fact] public void TemplateBinding_With_Null_Path_Works() { @@ -87,19 +46,5 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data Assert.Equal("Avalonia.Controls.Button", textBlock.Text); } } - - private Mock CreateTarget( - ITemplatedControl templatedParent = null, - string text = null) - { - var result = new Mock(); - - result.Setup(x => x.GetValue(Control.TemplatedParentProperty)).Returns(templatedParent); - result.Setup(x => x.GetValue((AvaloniaProperty)Control.TemplatedParentProperty)).Returns(templatedParent); - result.Setup(x => x.GetValue((AvaloniaProperty)TextBox.TextProperty)).Returns(text); - result.Setup(x => x.Bind(It.IsAny(), It.IsAny>(), It.IsAny())) - .Returns(Disposable.Empty); - return result; - } } } diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs index d55e34cbe6..8f2cba06a3 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs @@ -6,7 +6,7 @@ using System.Linq; using Avalonia.Controls; using Avalonia.Controls.Presenters; using Avalonia.Controls.Templates; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Media; using Avalonia.Styling; using Avalonia.UnitTests; diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/ResourceIncludeTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/ResourceIncludeTests.cs similarity index 96% rename from tests/Avalonia.Markup.Xaml.UnitTests/Data/ResourceIncludeTests.cs rename to tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/ResourceIncludeTests.cs index 6dc56e425c..a35c7bdd9b 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/ResourceIncludeTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/ResourceIncludeTests.cs @@ -4,7 +4,7 @@ using Avalonia.Media; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.Xaml.UnitTests.Data +namespace Avalonia.Markup.Xaml.UnitTests.MakrupExtensions { public class ResourceIncludeTests { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/TestValueConverter.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/TestValueConverter.cs index 57570d8f5c..cafad1056f 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/TestValueConverter.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/TestValueConverter.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using Avalonia.Data.Converters; namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/StyleTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/StyleTests.cs index e8e1646d44..91da8e18a1 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/StyleTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/StyleTests.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Reactive.Linq; using Avalonia.Controls; using Avalonia.Data; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Styling; using Avalonia.UnitTests; using Xunit; diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs index 0fcb9432ab..43df95cfce 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs @@ -4,7 +4,8 @@ using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Controls.Presenters; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Data.Converters; +using Avalonia.Markup.Data; using Avalonia.Markup.Xaml.Styling; using Avalonia.Markup.Xaml.Templates; using Avalonia.Media; diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs index f1f4792d34..2c7e850fee 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs @@ -2,7 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia.Controls; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Markup.Xaml.Styling; using Avalonia.Media; using Avalonia.Styling; diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/TreeDataTemplateTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/TreeDataTemplateTests.cs index a7ddfeeb00..cbcfa16771 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/TreeDataTemplateTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/TreeDataTemplateTests.cs @@ -3,7 +3,7 @@ using System.Linq; using Avalonia.Controls.Templates; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Markup.Xaml.Templates; using Avalonia.UnitTests; using Xunit; diff --git a/tests/Avalonia.Markup.UnitTests/ControlLocatorTests.cs b/tests/Avalonia.Styling.UnitTests/ControlLocatorTests.cs similarity index 95% rename from tests/Avalonia.Markup.UnitTests/ControlLocatorTests.cs rename to tests/Avalonia.Styling.UnitTests/ControlLocatorTests.cs index b3e983036d..519a456ee2 100644 --- a/tests/Avalonia.Markup.UnitTests/ControlLocatorTests.cs +++ b/tests/Avalonia.Styling.UnitTests/ControlLocatorTests.cs @@ -6,10 +6,11 @@ using System.Collections.Generic; using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia.Controls; +using Avalonia.LogicalTree; using Avalonia.UnitTests; using Xunit; -namespace Avalonia.Markup.UnitTests +namespace Avalonia.Styling.UnitTests { public class ControlLocatorTests { @@ -61,7 +62,7 @@ namespace Avalonia.Markup.UnitTests var locator = ControlLocator.Track(relativeTo, "target"); var target = new TextBlock { Name = "target" }; - var result = new List(); + var result = new List(); using (locator.Subscribe(x => result.Add(x))) { @@ -93,7 +94,7 @@ namespace Avalonia.Markup.UnitTests }; var locator = ControlLocator.Track(relativeTo, "target"); - var result = new List(); + var result = new List(); locator.Subscribe(x => result.Add(x)); var other = new TextBlock { Name = "target" }; @@ -138,7 +139,7 @@ namespace Avalonia.Markup.UnitTests var locator = ControlLocator.Track(relativeTo, "target"); var target = new TextBlock { Name = "target" }; - var result = new List(); + var result = new List(); using (locator.Subscribe(x => result.Add(x))) { diff --git a/tests/Avalonia.Styling.UnitTests/SetterTests.cs b/tests/Avalonia.Styling.UnitTests/SetterTests.cs index f376df4d0b..7c1623cf21 100644 --- a/tests/Avalonia.Styling.UnitTests/SetterTests.cs +++ b/tests/Avalonia.Styling.UnitTests/SetterTests.cs @@ -8,9 +8,10 @@ using Avalonia.Data; using Xunit; using System; using Avalonia.Controls.Templates; -using Avalonia.Markup.Xaml.Data; +using Avalonia.Markup.Data; using Avalonia.Markup; using System.Globalization; +using Avalonia.Data.Converters; namespace Avalonia.Styling.UnitTests {