diff --git a/.gitignore b/.gitignore
index 640725fa26..1d74816204 100644
--- a/.gitignore
+++ b/.gitignore
@@ -108,7 +108,7 @@ AppPackages/
# NCrunch
_NCrunch_*/
*.ncrunchsolution.user
-nCrunchTemp_*/
+nCrunchTemp_*
# Others
sql/
diff --git a/build.cake b/build.cake
index 45f2d9e18d..4e18f23780 100644
--- a/build.cake
+++ b/build.cake
@@ -6,7 +6,7 @@
#addin "nuget:?package=NuGet.Core&version=2.12.0"
#tool "nuget:?package=xunit.runner.console&version=2.2.0"
#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease"
-#tool "JetBrains.ReSharper.CommandLineTools"
+#tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2017.1.20170613.162720"
///////////////////////////////////////////////////////////////////////////////
// TOOLS
///////////////////////////////////////////////////////////////////////////////
diff --git a/samples/BindingTest/BindingTest.csproj b/samples/BindingTest/BindingTest.csproj
index 8e78b0c2cd..eab656eb33 100644
--- a/samples/BindingTest/BindingTest.csproj
+++ b/samples/BindingTest/BindingTest.csproj
@@ -66,6 +66,7 @@
+
diff --git a/samples/BindingTest/MainWindow.xaml b/samples/BindingTest/MainWindow.xaml
index 7d633bcd0c..3547e33181 100644
--- a/samples/BindingTest/MainWindow.xaml
+++ b/samples/BindingTest/MainWindow.xaml
@@ -97,8 +97,9 @@
-
+
+
diff --git a/samples/BindingTest/ViewModels/MainWindowViewModel.cs b/samples/BindingTest/ViewModels/MainWindowViewModel.cs
index 2ec052c258..d8ea280abf 100644
--- a/samples/BindingTest/ViewModels/MainWindowViewModel.cs
+++ b/samples/BindingTest/ViewModels/MainWindowViewModel.cs
@@ -15,6 +15,7 @@ namespace BindingTest.ViewModels
private string _stringValue = "Simple Binding";
private bool _booleanFlag = false;
private string _currentTime;
+ private NestedCommandViewModel _nested;
public MainWindowViewModel()
{
@@ -39,6 +40,7 @@ namespace BindingTest.ViewModels
{
BooleanFlag = !BooleanFlag;
StringValue = param.ToString();
+ NestedModel = _nested ?? new NestedCommandViewModel();
});
Task.Run(() =>
@@ -94,5 +96,11 @@ namespace BindingTest.ViewModels
public DataAnnotationsErrorViewModel DataAnnotationsValidation { get; } = new DataAnnotationsErrorViewModel();
public ExceptionErrorViewModel ExceptionDataValidation { get; } = new ExceptionErrorViewModel();
public IndeiErrorViewModel IndeiDataValidation { get; } = new IndeiErrorViewModel();
+
+ public NestedCommandViewModel NestedModel
+ {
+ get { return _nested; }
+ private set { this.RaiseAndSetIfChanged(ref _nested, value); }
+ }
}
}
diff --git a/samples/BindingTest/ViewModels/NestedCommandViewModel.cs b/samples/BindingTest/ViewModels/NestedCommandViewModel.cs
new file mode 100644
index 0000000000..3eca481c68
--- /dev/null
+++ b/samples/BindingTest/ViewModels/NestedCommandViewModel.cs
@@ -0,0 +1,20 @@
+using ReactiveUI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace BindingTest.ViewModels
+{
+ public class NestedCommandViewModel : ReactiveObject
+ {
+ public NestedCommandViewModel()
+ {
+ Command = ReactiveCommand.Create();
+ }
+
+ public ICommand Command { get; }
+ }
+}
diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj
index e0d12ce262..6906aed42b 100644
--- a/src/Avalonia.Base/Avalonia.Base.csproj
+++ b/src/Avalonia.Base/Avalonia.Base.csproj
@@ -2,6 +2,7 @@
netstandard1.3
false
+ Avalonia
true
diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index 1bdf1eb5e3..77cc90dd93 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -664,24 +664,11 @@ namespace Avalonia
if (notification != null)
{
- if (notification.ErrorType == BindingErrorType.Error)
- {
- Logger.Error(
- LogArea.Binding,
- this,
- "Error in binding to {Target}.{Property}: {Message}",
- this,
- property,
- ExceptionUtilities.GetMessage(notification.Error));
- }
-
- if (notification.HasValue)
- {
- value = notification.Value;
- }
+ notification.LogIfError(this, property);
+ value = notification.Value;
}
- if (notification == null || notification.HasValue)
+ if (notification == null || notification.ErrorType == BindingErrorType.Error || notification.HasValue)
{
var metadata = (IDirectPropertyMetadata)property.GetMetadata(GetType());
var accessor = (IDirectPropertyAccessor)GetRegistered(property);
diff --git a/src/Avalonia.Base/Data/BindingNotification.cs b/src/Avalonia.Base/Data/BindingNotification.cs
index 125c29b21b..5510a73b91 100644
--- a/src/Avalonia.Base/Data/BindingNotification.cs
+++ b/src/Avalonia.Base/Data/BindingNotification.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
+using Avalonia.Logging;
namespace Avalonia.Data
{
diff --git a/src/Avalonia.Base/Logging/LoggerExtensions.cs b/src/Avalonia.Base/Logging/LoggerExtensions.cs
new file mode 100644
index 0000000000..24e44bf9de
--- /dev/null
+++ b/src/Avalonia.Base/Logging/LoggerExtensions.cs
@@ -0,0 +1,53 @@
+using System;
+using Avalonia.Data;
+
+namespace Avalonia.Logging
+{
+ internal static class LoggerExtensions
+ {
+ public static void LogIfError(
+ this BindingNotification notification,
+ object source,
+ AvaloniaProperty property)
+ {
+ if (notification.ErrorType == BindingErrorType.Error)
+ {
+ if (notification.Error is AggregateException aggregate)
+ {
+ foreach (var inner in aggregate.InnerExceptions)
+ {
+ LogError(source, property, inner);
+ }
+ }
+ else
+ {
+ LogError(source, property, notification.Error);
+ }
+ }
+ }
+
+ private static void LogError(object source, AvaloniaProperty property, Exception e)
+ {
+ var level = LogEventLevel.Warning;
+
+ if (e is BindingChainException b &&
+ !string.IsNullOrEmpty(b.Expression) &&
+ string.IsNullOrEmpty(b.ExpressionErrorPoint))
+ {
+ // The error occurred at the root of the binding chain: it's possible that the
+ // DataContext isn't set up yet, so log at Information level instead of Warning
+ // to prevent spewing hundreds of errors.
+ level = LogEventLevel.Information;
+ }
+
+ Logger.Log(
+ level,
+ LogArea.Binding,
+ source,
+ "Error in binding to {Target}.{Property}: {Message}",
+ source,
+ property,
+ e.Message);
+ }
+ }
+}
diff --git a/src/Avalonia.Base/PriorityBindingEntry.cs b/src/Avalonia.Base/PriorityBindingEntry.cs
index eb7cf5414c..63f582a34c 100644
--- a/src/Avalonia.Base/PriorityBindingEntry.cs
+++ b/src/Avalonia.Base/PriorityBindingEntry.cs
@@ -98,7 +98,7 @@ namespace Avalonia
if (notification != null)
{
- if (notification.HasValue)
+ if (notification.HasValue || notification.ErrorType == BindingErrorType.Error)
{
Value = notification.Value;
_owner.Changed(this);
diff --git a/src/Avalonia.Base/PriorityValue.cs b/src/Avalonia.Base/PriorityValue.cs
index c33d50ff0e..3726fb7ae5 100644
--- a/src/Avalonia.Base/PriorityValue.cs
+++ b/src/Avalonia.Base/PriorityValue.cs
@@ -189,14 +189,7 @@ namespace Avalonia
/// The binding error.
public void LevelError(PriorityLevel level, BindingNotification error)
{
- Logger.Log(
- LogEventLevel.Error,
- LogArea.Binding,
- Owner,
- "Error in binding to {Target}.{Property}: {Message}",
- Owner,
- Property,
- error.Error.Message);
+ error.LogIfError(Owner, Property);
}
///
diff --git a/src/Avalonia.Base/Utilities/ExceptionUtilities.cs b/src/Avalonia.Base/Utilities/ExceptionUtilities.cs
deleted file mode 100644
index fa8c5be788..0000000000
--- a/src/Avalonia.Base/Utilities/ExceptionUtilities.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Avalonia.Utilities
-{
- internal static class ExceptionUtilities
- {
- public static string GetMessage(Exception e)
- {
- var aggregate = e as AggregateException;
-
- if (aggregate != null)
- {
- return string.Join(" | ", aggregate.InnerExceptions.Select(x => x.Message));
- }
-
- return e.Message;
- }
- }
-}
diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs
index 3d13608226..18eb1f7606 100644
--- a/src/Avalonia.Controls/Application.cs
+++ b/src/Avalonia.Controls/Application.cs
@@ -39,6 +39,7 @@ namespace Avalonia
private readonly Lazy _clipboard =
new Lazy(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard)));
private readonly Styler _styler = new Styler();
+ private Styles _styles;
///
/// Initializes a new instance of the class.
@@ -65,11 +66,7 @@ namespace Avalonia
///
/// The application's global data templates.
///
- public DataTemplates DataTemplates
- {
- get { return _dataTemplates ?? (_dataTemplates = new DataTemplates()); }
- set { _dataTemplates = value; }
- }
+ public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
///
/// Gets the application's focus manager.
@@ -109,13 +106,19 @@ namespace Avalonia
///
/// Global styles apply to all windows in the application.
///
- public Styles Styles { get; } = new Styles();
+ public Styles Styles => _styles ?? (_styles = new Styles());
+
+ ///
+ bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
///
/// Gets the styling parent of the application, which is null.
///
IStyleHost IStyleHost.StylingParent => null;
+ ///
+ bool IStyleHost.IsStylesInitialized => _styles != null;
+
///
/// Initializes the application by loading XAML etc.
///
diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs
index 78bbd836be..52329b9c88 100644
--- a/src/Avalonia.Controls/Button.cs
+++ b/src/Avalonia.Controls/Button.cs
@@ -4,6 +4,7 @@
using System;
using System.Linq;
using System.Windows.Input;
+using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Rendering;
@@ -41,8 +42,9 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty CommandProperty =
- AvaloniaProperty.Register
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;NETSTANDARD
- prompt
- 4
- bin\Debug\Avalonia.DotNetCoreRuntime.XML
-
-
- pdbonly
- true
- bin\Release\
- TRACE;NETSTANDARD
- prompt
- 4
- bin\Release\Avalonia.DotNetCoreRuntime.XML
+
+ bin\$(Configuration)\Avalonia.DotNetCoreRuntime.XML
diff --git a/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs b/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs
index 9a54cdbab0..bae97f503d 100644
--- a/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs
+++ b/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs
@@ -59,7 +59,11 @@ namespace Avalonia
from attribute in assembly.GetCustomAttributes()
where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker)
orderby attribute.Priority ascending
- select attribute).First();
+ select attribute).FirstOrDefault();
+ if (windowingSubsystemAttribute == null)
+ {
+ throw new InvalidOperationException("No windowing subsystem found. Are you missing assembly references?");
+ }
var renderingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies()
from attribute in assembly.GetCustomAttributes()
@@ -67,7 +71,12 @@ namespace Avalonia
where attribute.RequiresWindowingSubsystem == null
|| attribute.RequiresWindowingSubsystem == windowingSubsystemAttribute.Name
orderby attribute.Priority ascending
- select attribute).First();
+ select attribute).FirstOrDefault();
+
+ if (renderingSubsystemAttribute == null)
+ {
+ throw new InvalidOperationException("No rendering subsystem found. Are you missing assembly references?");
+ }
UseWindowingSubsystem(() => windowingSubsystemAttribute.InitializationType
.GetRuntimeMethod(windowingSubsystemAttribute.InitializationMethod, Type.EmptyTypes).Invoke(null, null),
diff --git a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
index 2fbcba40c8..e2c866fe3d 100644
--- a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
+++ b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
@@ -44,6 +44,9 @@
+
+ Properties\SharedAssemblyInfo.cs
+
diff --git a/src/Avalonia.DotNetFrameworkRuntime/Properties/AssemblyInfo.cs b/src/Avalonia.DotNetFrameworkRuntime/Properties/AssemblyInfo.cs
index f55d3056f6..3a91d50a24 100644
--- a/src/Avalonia.DotNetFrameworkRuntime/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.DotNetFrameworkRuntime/Properties/AssemblyInfo.cs
@@ -1,18 +1,10 @@
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Avalonia.DotNetFrameworkRuntime")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Avalonia.DotNetFrameworkRuntime")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
@@ -21,16 +13,3 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4a1abb09-9047-4bd5-a4ad-a055e52c5ee0")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Avalonia.Interactivity/Interactive.cs b/src/Avalonia.Interactivity/Interactive.cs
index e38b348179..78df6f6151 100644
--- a/src/Avalonia.Interactivity/Interactive.cs
+++ b/src/Avalonia.Interactivity/Interactive.cs
@@ -16,14 +16,18 @@ namespace Avalonia.Interactivity
///
public class Interactive : Layoutable, IInteractive
{
- private readonly Dictionary> _eventHandlers =
- new Dictionary>();
+ private Dictionary> _eventHandlers;
///
/// Gets the interactive parent of the object for bubbling and tunnelling events.
///
IInteractive IInteractive.InteractiveParent => ((IVisual)this).VisualParent as IInteractive;
+ private Dictionary> EventHandlers
+ {
+ get { return _eventHandlers ?? (_eventHandlers = new Dictionary>()); }
+ }
+
///
/// Adds a handler for the specified routed event.
///
@@ -43,10 +47,10 @@ namespace Avalonia.Interactivity
List subscriptions;
- if (!_eventHandlers.TryGetValue(routedEvent, out subscriptions))
+ if (!EventHandlers.TryGetValue(routedEvent, out subscriptions))
{
subscriptions = new List();
- _eventHandlers.Add(routedEvent, subscriptions);
+ EventHandlers.Add(routedEvent, subscriptions);
}
var sub = new EventSubscription
@@ -89,9 +93,9 @@ namespace Avalonia.Interactivity
Contract.Requires(routedEvent != null);
Contract.Requires(handler != null);
- List subscriptions;
+ List subscriptions = null;
- if (_eventHandlers.TryGetValue(routedEvent, out subscriptions))
+ if (_eventHandlers?.TryGetValue(routedEvent, out subscriptions) == true)
{
subscriptions.RemoveAll(x => x.Handler == handler);
}
@@ -181,9 +185,9 @@ namespace Avalonia.Interactivity
e.RoutedEvent.InvokeRaised(this, e);
- List subscriptions;
+ List subscriptions = null;
- if (_eventHandlers.TryGetValue(e.RoutedEvent, out subscriptions))
+ if (_eventHandlers?.TryGetValue(e.RoutedEvent, out subscriptions) == true)
{
foreach (var sub in subscriptions.ToList())
{
diff --git a/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj b/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
index 508ede7f7d..9ac40cba07 100644
--- a/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
+++ b/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
@@ -23,6 +23,9 @@
bin\Release\Avalonia.Logging.Serilog.XML
true
+
+
+
diff --git a/src/Avalonia.Logging.Serilog/Properties/AssemblyInfo.cs b/src/Avalonia.Logging.Serilog/Properties/AssemblyInfo.cs
index 64c0eaffae..35b2e48f70 100644
--- a/src/Avalonia.Logging.Serilog/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Logging.Serilog/Properties/AssemblyInfo.cs
@@ -1,30 +1,3 @@
-using System.Resources;
using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
[assembly: AssemblyTitle("Avalonia.Serilog")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Avalonia.Serilog")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: NeutralResourcesLanguage("en")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
index 2d66b62eab..22d815d786 100644
--- a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
+++ b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
@@ -25,6 +25,7 @@
+
diff --git a/src/Avalonia.ReactiveUI/Properties/AssemblyInfo.cs b/src/Avalonia.ReactiveUI/Properties/AssemblyInfo.cs
index 358c6224fb..c8a5c5cc41 100644
--- a/src/Avalonia.ReactiveUI/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.ReactiveUI/Properties/AssemblyInfo.cs
@@ -1,33 +1,9 @@
// 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.Resources;
using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Avalonia.ReactiveUI")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Avalonia.ReactiveUI")]
-[assembly: AssemblyCopyright("Copyright \u00A9 2015")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: NeutralResourcesLanguage("en")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Avalonia.Styling/Styling/IStyleHost.cs b/src/Avalonia.Styling/Styling/IStyleHost.cs
index 8422f18b46..b225419c2d 100644
--- a/src/Avalonia.Styling/Styling/IStyleHost.cs
+++ b/src/Avalonia.Styling/Styling/IStyleHost.cs
@@ -1,6 +1,8 @@
// 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;
+
namespace Avalonia.Styling
{
///
@@ -8,6 +10,15 @@ namespace Avalonia.Styling
///
public interface IStyleHost
{
+ ///
+ /// Gets a value indicating whether is initialized.
+ ///
+ ///
+ /// The property may be lazily initialized, if so this property
+ /// indicates whether it has been initialized.
+ ///
+ bool IsStylesInitialized { get; }
+
///
/// Gets the styles for the element.
///
@@ -17,6 +28,5 @@ namespace Avalonia.Styling
/// Gets the parent style host element.
///
IStyleHost StylingParent { get; }
-
}
}
diff --git a/src/Avalonia.Styling/Styling/StyleExtensions.cs b/src/Avalonia.Styling/Styling/StyleExtensions.cs
index e1073335a0..d53d00aed3 100644
--- a/src/Avalonia.Styling/Styling/StyleExtensions.cs
+++ b/src/Avalonia.Styling/Styling/StyleExtensions.cs
@@ -23,11 +23,14 @@ namespace Avalonia.Styling
while (control != null)
{
- var result = control.Styles.FindResource(name);
-
- if (result != AvaloniaProperty.UnsetValue)
+ if (control.IsStylesInitialized)
{
- return result;
+ var result = control.Styles.FindResource(name);
+
+ if (result != AvaloniaProperty.UnsetValue)
+ {
+ return result;
+ }
}
control = control.StylingParent;
diff --git a/src/Avalonia.Styling/Styling/Styler.cs b/src/Avalonia.Styling/Styling/Styler.cs
index 880e435b58..7ac5c89005 100644
--- a/src/Avalonia.Styling/Styling/Styler.cs
+++ b/src/Avalonia.Styling/Styling/Styler.cs
@@ -29,7 +29,10 @@ namespace Avalonia.Styling
ApplyStyles(control, parentContainer);
}
- styleHost.Styles.Attach(control, styleHost);
+ if (styleHost.IsStylesInitialized)
+ {
+ styleHost.Styles.Attach(control, styleHost);
+ }
}
}
}
diff --git a/src/Avalonia.Visuals/Media/PathMarkupParser.cs b/src/Avalonia.Visuals/Media/PathMarkupParser.cs
index fad55ed531..145013d76b 100644
--- a/src/Avalonia.Visuals/Media/PathMarkupParser.cs
+++ b/src/Avalonia.Visuals/Media/PathMarkupParser.cs
@@ -126,7 +126,9 @@ namespace Avalonia.Media
case Command.CubicBezierCurve:
{
Point point1 = ReadPoint(reader, point, relative);
+ ReadSeparator(reader);
Point point2 = ReadPoint(reader, point, relative);
+ ReadSeparator(reader);
point = ReadPoint(reader, point, relative);
_context.CubicBezierTo(point1, point2, point);
break;
diff --git a/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj b/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj
index d09fd2ddc6..460db98895 100644
--- a/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj
+++ b/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj
@@ -47,6 +47,9 @@
+
+ Properties\SharedAssemblyInfo.cs
+
diff --git a/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs b/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs
index dc7d815ddc..709f1eb22a 100644
--- a/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs
+++ b/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs
@@ -11,13 +11,6 @@ using System.Runtime.InteropServices;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Avalonia.Cairo")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Avalonia.Cairo")]
-[assembly: AssemblyCopyright("Copyright \u00A9 2014")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
@@ -27,19 +20,6 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f999ba8b-64e7-40cc-98a4-003f1852d2a3")]
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
-
[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 3, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")]
[assembly: ExportRenderingSubsystem(OperatingSystemType.Linux, 2, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")]
[assembly: ExportRenderingSubsystem(OperatingSystemType.OSX, 3, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")]
diff --git a/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj b/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
index b51377f29c..6049869424 100644
--- a/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
+++ b/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
@@ -39,6 +39,9 @@
+
+ Properties\SharedAssemblyInfo.cs
+
diff --git a/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs b/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs
index 6d1eb24836..67e5f6dc17 100644
--- a/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs
+++ b/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs
@@ -4,23 +4,10 @@
using Avalonia.Gtk;
using Avalonia.Platform;
using System.Reflection;
-using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("Avalonia.Gtk")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("")]
-[assembly: AssemblyCopyright("steven")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-[assembly: AssemblyVersion("1.0.*")]
[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 3, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))]
[assembly: ExportWindowingSubsystem(OperatingSystemType.Linux, 2, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))]
diff --git a/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
index d292e99b30..0f4b8c2e1b 100644
--- a/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
+++ b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
@@ -24,6 +24,7 @@
true
+
KeyTransform.cs
diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs b/src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs
index fc76fefd1a..c932aac950 100644
--- a/src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs
+++ b/src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs
@@ -36,6 +36,8 @@ namespace Avalonia.Gtk3.Interop
public static unsafe string StringFromPtr(IntPtr s)
{
var pstr = (byte*)s;
+ if (pstr == null)
+ return null;
int len;
for (len = 0; pstr[len] != 0; len++) ;
var bytes = new byte[len];
diff --git a/src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs b/src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
index 6b040240c4..034b73f699 100644
--- a/src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
+++ b/src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
@@ -1,7 +1,4 @@
-using System.Resources;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
+using System.Reflection;
using Avalonia.Gtk3;
using Avalonia.Platform;
@@ -9,27 +6,7 @@ using Avalonia.Platform;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Avalonia.Gtk3")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Avalonia.Gtk3")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: NeutralResourcesLanguage("en")]
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 2, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]
[assembly: ExportWindowingSubsystem(OperatingSystemType.Linux, 1, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]
[assembly: ExportWindowingSubsystem(OperatingSystemType.OSX, 2, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]
\ No newline at end of file
diff --git a/src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs b/src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs
index 7ad8486bdd..1e55e17195 100644
--- a/src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs
+++ b/src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs
@@ -239,17 +239,7 @@ namespace Avalonia.Markup.Data
if (broken != null)
{
- // We've received notification of a broken expression due to a null value
- // somewhere in the chain. If this null value occurs at the first node then we
- // ignore it, as its likely that e.g. the DataContext has not yet been set up.
- if (broken.HasNodes)
- {
- broken.Commit(Description);
- }
- else
- {
- o = AvaloniaProperty.UnsetValue;
- }
+ broken.Commit(Description);
}
return o;
}
diff --git a/src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs b/src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs
index 51afe1ffbf..ddfcf531eb 100644
--- a/src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs
+++ b/src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs
@@ -32,10 +32,12 @@ namespace Avalonia.Markup.Data
public void Commit(string expression)
{
Expression = expression;
- ExpressionErrorPoint = string.Join(".", _nodes.Reverse())
- .Replace(".!", "!")
- .Replace(".[", "[")
- .Replace(".^", "^");
+ ExpressionErrorPoint = _nodes != null ?
+ string.Join(".", _nodes.Reverse())
+ .Replace(".!", "!")
+ .Replace(".[", "[")
+ .Replace(".^", "^") :
+ string.Empty;
_nodes = null;
}
}
diff --git a/src/Shared/PlatformSupport/AssetLoader.cs b/src/Shared/PlatformSupport/AssetLoader.cs
index bbf19f731d..4287fd0b9e 100644
--- a/src/Shared/PlatformSupport/AssetLoader.cs
+++ b/src/Shared/PlatformSupport/AssetLoader.cs
@@ -137,7 +137,7 @@ namespace Avalonia.Shared.PlatformSupport
{
// iOS does not support loading assemblies dynamically!
//
-#if NETSTANDARD
+#if NETCOREAPP1_0
AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(new AssemblyName(name)));
#elif __IOS__
throw new InvalidOperationException(
diff --git a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs b/src/Shared/PlatformSupport/StandardRuntimePlatform.cs
index 1f42aec16e..e7402fb23c 100644
--- a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs
+++ b/src/Shared/PlatformSupport/StandardRuntimePlatform.cs
@@ -12,7 +12,7 @@ namespace Avalonia.Shared.PlatformSupport
internal partial class StandardRuntimePlatform : IRuntimePlatform
{
-#if NETSTANDARD
+#if NETCOREAPP1_0
public void PostThreadPoolItem(Action cb) => ThreadPool.QueueUserWorkItem(_ => cb(), null);
#else
public Assembly[] GetLoadedAssemblies() => AppDomain.CurrentDomain.GetAssemblies();
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs
index cd8184b140..66b237de06 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs
@@ -314,7 +314,7 @@ namespace Avalonia.Base.UnitTests
new InvalidOperationException("Foo"),
BindingErrorType.Error));
- Assert.Equal(6.7, target.GetValue(Class1.QuxProperty));
+ Assert.Equal(5.6, target.GetValue(Class1.QuxProperty));
}
[Fact]
@@ -343,7 +343,7 @@ namespace Avalonia.Base.UnitTests
LogCallback checkLogMessage = (level, area, src, mt, pv) =>
{
- if (level == LogEventLevel.Error &&
+ if (level == LogEventLevel.Warning &&
area == LogArea.Binding &&
mt == expectedMessageTemplate)
{
@@ -359,7 +359,7 @@ namespace Avalonia.Base.UnitTests
new InvalidOperationException("Foo"),
BindingErrorType.Error));
- Assert.Equal(6.7, target.GetValue(Class1.QuxProperty));
+ Assert.Equal(5.6, target.GetValue(Class1.QuxProperty));
Assert.True(called);
}
}
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs
index ecb555252d..05339c43b0 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs
@@ -352,14 +352,14 @@ namespace Avalonia.Base.UnitTests
}
[Fact]
- public void BindingError_Does_Not_Cause_Target_Update()
+ public void DataValidationError_Does_Not_Cause_Target_Update()
{
var target = new Class1();
var source = new Subject
-
\ No newline at end of file
+
+
+
+
+
diff --git a/tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs b/tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
index 6b7c73da2a..cdfb253bf4 100644
--- a/tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
+++ b/tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
@@ -193,6 +193,7 @@ namespace Avalonia.Layout.UnitTests
.Bind().ToConstant(new Avalonia.Controls.UnitTests.WindowingPlatformMock(() => windowImpl.Object));
var theme = new DefaultTheme();
+ globalStyles.Setup(x => x.IsStylesInitialized).Returns(true);
globalStyles.Setup(x => x.Styles).Returns(theme);
}
}
diff --git a/tests/Avalonia.LeakTests/ControlTests.cs b/tests/Avalonia.LeakTests/ControlTests.cs
index e0b0d4a4c0..12ac8d3af6 100644
--- a/tests/Avalonia.LeakTests/ControlTests.cs
+++ b/tests/Avalonia.LeakTests/ControlTests.cs
@@ -276,7 +276,7 @@ namespace Avalonia.LeakTests
{
Content = target = new TreeView
{
- DataTemplates = new DataTemplates
+ DataTemplates =
{
new FuncTreeDataTemplate(
x => new TextBlock { Text = x.Name },
diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs b/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs
index 4cb2061c9e..60174e65e6 100644
--- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs
+++ b/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs
@@ -67,49 +67,69 @@ namespace Avalonia.Markup.UnitTests.Data
}
[Fact]
- public async Task Should_Return_UnsetValue_For_Root_Null()
+ public async Task Should_Return_BindingNotification_Error_For_Root_Null()
{
var data = new Class3 { Foo = "foo" };
var target = new ExpressionObserver(default(object), "Foo");
var result = await target.Take(1);
- Assert.Equal(AvaloniaProperty.UnsetValue, result);
+ Assert.Equal(
+ new BindingNotification(
+ new MarkupBindingChainException("Null value", "Foo", string.Empty),
+ BindingErrorType.Error,
+ AvaloniaProperty.UnsetValue),
+ result);
GC.KeepAlive(data);
}
[Fact]
- public async Task Should_Return_UnsetValue_For_Root_UnsetValue()
+ public async Task Should_Return_BindingNotification_Error_For_Root_UnsetValue()
{
var data = new Class3 { Foo = "foo" };
var target = new ExpressionObserver(AvaloniaProperty.UnsetValue, "Foo");
var result = await target.Take(1);
- Assert.Equal(AvaloniaProperty.UnsetValue, result);
+ Assert.Equal(
+ new BindingNotification(
+ new MarkupBindingChainException("Null value", "Foo", string.Empty),
+ BindingErrorType.Error,
+ AvaloniaProperty.UnsetValue),
+ result);
GC.KeepAlive(data);
}
[Fact]
- public async Task Should_Return_UnsetValue_For_Observable_Root_Null()
+ public async Task Should_Return_BindingNotification_Error_For_Observable_Root_Null()
{
var data = new Class3 { Foo = "foo" };
var target = new ExpressionObserver(Observable.Return(default(object)), "Foo");
var result = await target.Take(1);
- Assert.Equal(AvaloniaProperty.UnsetValue, result);
+ Assert.Equal(
+ new BindingNotification(
+ new MarkupBindingChainException("Null value", "Foo", string.Empty),
+ BindingErrorType.Error,
+ AvaloniaProperty.UnsetValue),
+ result);
GC.KeepAlive(data);
}
[Fact]
- public async Task Should_Return_UnsetValue_For_Observable_Root_UnsetValue()
+ public async void Should_Return_BindingNotification_Error_For_Observable_Root_UnsetValue()
{
var data = new Class3 { Foo = "foo" };
var target = new ExpressionObserver(Observable.Return(AvaloniaProperty.UnsetValue), "Foo");
var result = await target.Take(1);
- Assert.Equal(AvaloniaProperty.UnsetValue, result);
+ Assert.Equal(
+ new BindingNotification(
+ new MarkupBindingChainException("Null value", "Foo", string.Empty),
+ BindingErrorType.Error,
+ AvaloniaProperty.UnsetValue),
+ result);
GC.KeepAlive(data);
}
@@ -117,7 +137,7 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact]
public async Task Should_Get_Simple_Property_Chain()
{
- var data = new { Foo = new { Bar = new { Baz = "baz" } } };
+ var data = new { Foo = new { Bar = new { Baz = "baz" } } };
var target = new ExpressionObserver(data, "Foo.Bar.Baz");
var result = await target.Take(1);
@@ -215,7 +235,7 @@ namespace Avalonia.Markup.UnitTests.Data
var target = new ExpressionObserver(data, "Bar");
var result = new List