Browse Source

Merge remote-tracking branch 'origin/master' into pr/1123-clean-up-build-warnings

pull/1123/head
Steven Kirk 9 years ago
parent
commit
e06cdd8810
  1. 2
      .gitignore
  2. 2
      build.cake
  3. 1
      samples/BindingTest/BindingTest.csproj
  4. 3
      samples/BindingTest/MainWindow.xaml
  5. 8
      samples/BindingTest/ViewModels/MainWindowViewModel.cs
  6. 20
      samples/BindingTest/ViewModels/NestedCommandViewModel.cs
  7. 1
      src/Avalonia.Base/Avalonia.Base.csproj
  8. 19
      src/Avalonia.Base/AvaloniaObject.cs
  9. 1
      src/Avalonia.Base/Data/BindingNotification.cs
  10. 53
      src/Avalonia.Base/Logging/LoggerExtensions.cs
  11. 2
      src/Avalonia.Base/PriorityBindingEntry.cs
  12. 9
      src/Avalonia.Base/PriorityValue.cs
  13. 23
      src/Avalonia.Base/Utilities/ExceptionUtilities.cs
  14. 15
      src/Avalonia.Controls/Application.cs
  15. 24
      src/Avalonia.Controls/Button.cs
  16. 22
      src/Avalonia.Controls/Control.cs
  17. 14
      src/Avalonia.Controls/IControl.cs
  18. 6
      src/Avalonia.Controls/IGlobalDataTemplates.cs
  19. 2
      src/Avalonia.Controls/MenuItem.cs
  20. 24
      src/Avalonia.Controls/Templates/DataTemplateExtensions.cs
  21. 27
      src/Avalonia.Controls/Templates/IDataTemplateHost.cs
  22. 2
      src/Avalonia.Diagnostics/DevTools.xaml.cs
  23. 2
      src/Avalonia.Diagnostics/Views/ControlDetailsView.cs
  24. 20
      src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj
  25. 13
      src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs
  26. 3
      src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
  27. 21
      src/Avalonia.DotNetFrameworkRuntime/Properties/AssemblyInfo.cs
  28. 20
      src/Avalonia.Interactivity/Interactive.cs
  29. 3
      src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
  30. 27
      src/Avalonia.Logging.Serilog/Properties/AssemblyInfo.cs
  31. 1
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  32. 24
      src/Avalonia.ReactiveUI/Properties/AssemblyInfo.cs
  33. 12
      src/Avalonia.Styling/Styling/IStyleHost.cs
  34. 11
      src/Avalonia.Styling/Styling/StyleExtensions.cs
  35. 5
      src/Avalonia.Styling/Styling/Styler.cs
  36. 2
      src/Avalonia.Visuals/Media/PathMarkupParser.cs
  37. 3
      src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj
  38. 20
      src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs
  39. 3
      src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
  40. 13
      src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs
  41. 1
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
  42. 2
      src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs
  43. 25
      src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
  44. 12
      src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs
  45. 10
      src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs
  46. 2
      src/Shared/PlatformSupport/AssetLoader.cs
  47. 2
      src/Shared/PlatformSupport/StandardRuntimePlatform.cs
  48. 6
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs
  49. 6
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs
  50. 125
      tests/Avalonia.Controls.UnitTests/ButtonTests.cs
  51. 2
      tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs
  52. 8
      tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
  53. 2
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Unrooted.cs
  54. 1
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
  55. 8
      tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs
  56. 4
      tests/Avalonia.Controls.UnitTests/TabControlTests.cs
  57. 28
      tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
  58. 2
      tests/Avalonia.Controls.UnitTests/UserControlTests.cs
  59. 6
      tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj
  60. 1
      tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
  61. 2
      tests/Avalonia.LeakTests/ControlTests.cs
  62. 55
      tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Property.cs
  63. 4
      tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs
  64. 2
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlBindingTests.cs
  65. 20
      tests/Avalonia.Styling.UnitTests/ResourceTests.cs
  66. 4
      tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs

2
.gitignore

@ -108,7 +108,7 @@ AppPackages/
# NCrunch
_NCrunch_*/
*.ncrunchsolution.user
nCrunchTemp_*/
nCrunchTemp_*
# Others
sql/

2
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
///////////////////////////////////////////////////////////////////////////////

1
samples/BindingTest/BindingTest.csproj

@ -66,6 +66,7 @@
<Compile Include="ViewModels\IndeiErrorViewModel.cs" />
<Compile Include="ViewModels\ExceptionErrorViewModel.cs" />
<Compile Include="ViewModels\MainWindowViewModel.cs" />
<Compile Include="ViewModels\NestedCommandViewModel.cs" />
<Compile Include="ViewModels\TestItem.cs" />
</ItemGroup>
<ItemGroup>

3
samples/BindingTest/MainWindow.xaml

@ -97,8 +97,9 @@
<Button Content="Button" Command="{Binding StringValueCommand}" CommandParameter="Button"/>
<ToggleButton Content="ToggleButton" IsChecked="{Binding BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="ToggleButton"/>
<CheckBox Content="CheckBox" IsChecked="{Binding !BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="CheckBox"/>
<RadioButton Content="RadionButton" IsChecked="{Binding !!BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="RadioButton"/>
<RadioButton Content="Radio Button" IsChecked="{Binding !!BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="RadioButton"/>
<TextBox Text="{Binding Path=StringValue}"/>
<Button Content="Nested View Model Button" Name="NestedTest" Command="{Binding NestedModel.Command}" />
</StackPanel>
</TabItem>
</TabControl>

8
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); }
}
}
}

20
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; }
}
}

1
src/Avalonia.Base/Avalonia.Base.csproj

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RootNamespace>Avalonia</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>

19
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);

1
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
{

53
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);
}
}
}

2
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);

9
src/Avalonia.Base/PriorityValue.cs

@ -189,14 +189,7 @@ namespace Avalonia
/// <param name="error">The binding error.</param>
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);
}
/// <summary>

23
src/Avalonia.Base/Utilities/ExceptionUtilities.cs

@ -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;
}
}
}

15
src/Avalonia.Controls/Application.cs

@ -39,6 +39,7 @@ namespace Avalonia
private readonly Lazy<IClipboard> _clipboard =
new Lazy<IClipboard>(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard)));
private readonly Styler _styler = new Styler();
private Styles _styles;
/// <summary>
/// Initializes a new instance of the <see cref="Application"/> class.
@ -65,11 +66,7 @@ namespace Avalonia
/// <value>
/// The application's global data templates.
/// </value>
public DataTemplates DataTemplates
{
get { return _dataTemplates ?? (_dataTemplates = new DataTemplates()); }
set { _dataTemplates = value; }
}
public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
/// <summary>
/// Gets the application's focus manager.
@ -109,13 +106,19 @@ namespace Avalonia
/// <remarks>
/// Global styles apply to all windows in the application.
/// </remarks>
public Styles Styles { get; } = new Styles();
public Styles Styles => _styles ?? (_styles = new Styles());
/// <inheritdoc/>
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
/// <summary>
/// Gets the styling parent of the application, which is null.
/// </summary>
IStyleHost IStyleHost.StylingParent => null;
/// <inheritdoc/>
bool IStyleHost.IsStylesInitialized => _styles != null;
/// <summary>
/// Initializes the application by loading XAML etc.
/// </summary>

24
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
/// <summary>
/// Defines the <see cref="Command"/> property.
/// </summary>
public static readonly StyledProperty<ICommand> CommandProperty =
AvaloniaProperty.Register<Button, ICommand>(nameof(Command));
public static readonly DirectProperty<Button, ICommand> CommandProperty =
AvaloniaProperty.RegisterDirect<Button, ICommand>(nameof(Command),
button => button.Command, (button, command) => button.Command = command, enableDataValidation: true);
/// <summary>
/// Defines the <see cref="HotKey"/> property.
@ -68,6 +70,8 @@ namespace Avalonia.Controls
public static readonly RoutedEvent<RoutedEventArgs> ClickEvent =
RoutedEvent.Register<Button, RoutedEventArgs>("Click", RoutingStrategies.Bubble);
private ICommand _command;
/// <summary>
/// Initializes static members of the <see cref="Button"/> class.
/// </summary>
@ -102,8 +106,8 @@ namespace Avalonia.Controls
/// </summary>
public ICommand Command
{
get { return GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
get { return _command; }
set { SetAndRaise(CommandProperty, ref _command, value); }
}
/// <summary>
@ -250,6 +254,18 @@ namespace Avalonia.Controls
}
}
protected override void UpdateDataValidation(AvaloniaProperty property, BindingNotification status)
{
base.UpdateDataValidation(property, status);
if(property == CommandProperty)
{
if(status?.ErrorType == BindingErrorType.Error)
{
IsEnabled = false;
}
}
}
/// <summary>
/// Called when the <see cref="Command"/> property changes.
/// </summary>

22
src/Avalonia.Controls/Control.cs

@ -97,8 +97,8 @@ namespace Avalonia.Controls
private bool _isAttachedToLogicalTree;
private IAvaloniaList<ILogical> _logicalChildren;
private INameScope _nameScope;
private Styles _styles;
private bool _styled;
private Styles _styles;
private Subject<IStyleable> _styleDetach = new Subject<IStyleable>();
/// <summary>
@ -243,11 +243,7 @@ namespace Avalonia.Controls
/// Each control may define data templates which are applied to the control itself and its
/// children.
/// </remarks>
public DataTemplates DataTemplates
{
get { return _dataTemplates ?? (_dataTemplates = new DataTemplates()); }
set { _dataTemplates = value; }
}
public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
/// <summary>
/// Gets a value that indicates whether the element has finished initialization.
@ -259,18 +255,14 @@ namespace Avalonia.Controls
public bool IsInitialized { get; private set; }
/// <summary>
/// Gets or sets the styles for the control.
/// Gets the styles for the control.
/// </summary>
/// <remarks>
/// Styles for the entire application are added to the Application.Styles collection, but
/// each control may in addition define its own styles which are applied to the control
/// itself and its children.
/// </remarks>
public Styles Styles
{
get { return _styles ?? (_styles = new Styles()); }
set { _styles = value; }
}
public Styles Styles => _styles ?? (_styles = new Styles());
/// <summary>
/// Gets the control's logical parent.
@ -304,6 +296,9 @@ namespace Avalonia.Controls
internal set { SetValue(TemplatedParentProperty, value); }
}
/// <inheritdoc/>
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
/// <summary>
/// Gets a value indicating whether the element is attached to a rooted logical tree.
/// </summary>
@ -336,6 +331,9 @@ namespace Avalonia.Controls
/// <inheritdoc/>
IObservable<IStyleable> IStyleable.StyleDetach => _styleDetach;
/// <inheritdoc/>
bool IStyleHost.IsStylesInitialized => _styles != null;
/// <inheritdoc/>
IStyleHost IStyleHost.StylingParent => (IStyleHost)InheritanceParent;

14
src/Avalonia.Controls/IControl.cs

@ -14,7 +14,14 @@ namespace Avalonia.Controls
/// <summary>
/// Interface for Avalonia controls.
/// </summary>
public interface IControl : IVisual, ILogical, ILayoutable, IInputElement, INamed, IStyleable, IStyleHost
public interface IControl : IVisual,
IDataTemplateHost,
ILogical,
ILayoutable,
IInputElement,
INamed,
IStyleable,
IStyleHost
{
/// <summary>
/// Occurs when the control has finished initialization.
@ -31,11 +38,6 @@ namespace Avalonia.Controls
/// </summary>
object DataContext { get; set; }
/// <summary>
/// Gets the data templates for the control.
/// </summary>
DataTemplates DataTemplates { get; }
/// <summary>
/// Gets a value that indicates whether the element has finished initialization.
/// </summary>

6
src/Avalonia.Controls/IGlobalDataTemplates.cs

@ -8,11 +8,7 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the application-global data templates.
/// </summary>
public interface IGlobalDataTemplates
public interface IGlobalDataTemplates : IDataTemplateHost
{
/// <summary>
/// Gets the application-global data templates.
/// </summary>
DataTemplates DataTemplates { get; }
}
}

2
src/Avalonia.Controls/MenuItem.cs

@ -24,7 +24,7 @@ namespace Avalonia.Controls
/// Defines the <see cref="Command"/> property.
/// </summary>
public static readonly StyledProperty<ICommand> CommandProperty =
Button.CommandProperty.AddOwner<MenuItem>();
AvaloniaProperty.Register<MenuItem, ICommand>(nameof(Command));
/// <summary>
/// Defines the <see cref="HotKey"/> property.

24
src/Avalonia.Controls/Templates/DataTemplateExtensions.cs

@ -17,8 +17,8 @@ namespace Avalonia.Controls.Templates
/// <param name="control">The control searching for the data template.</param>
/// <param name="data">The data.</param>
/// <param name="primary">
/// An optional primary template that can will be tried before the
/// <see cref="IControl.DataTemplates"/> in the tree are searched.
/// An optional primary template that can will be tried before the DataTemplates in the
/// tree are searched.
/// </param>
/// <returns>The data template or null if no matching data template was found.</returns>
public static IDataTemplate FindDataTemplate(
@ -31,13 +31,16 @@ namespace Avalonia.Controls.Templates
return primary;
}
foreach (var i in control.GetSelfAndLogicalAncestors().OfType<IControl>())
foreach (var i in control.GetSelfAndLogicalAncestors().OfType<IDataTemplateHost>())
{
foreach (IDataTemplate dt in i.DataTemplates)
if (i.IsDataTemplatesInitialized)
{
if (dt.Match(data))
foreach (IDataTemplate dt in i.DataTemplates)
{
return dt;
if (dt.Match(data))
{
return dt;
}
}
}
}
@ -46,11 +49,14 @@ namespace Avalonia.Controls.Templates
if (global != null)
{
foreach (IDataTemplate dt in global.DataTemplates)
if (global.IsDataTemplatesInitialized)
{
if (dt.Match(data))
foreach (IDataTemplate dt in global.DataTemplates)
{
return dt;
if (dt.Match(data))
{
return dt;
}
}
}
}

27
src/Avalonia.Controls/Templates/IDataTemplateHost.cs

@ -0,0 +1,27 @@
// 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.Controls.Templates
{
/// <summary>
/// Defines an element that has a <see cref="DataTemplates"/> collection.
/// </summary>
public interface IDataTemplateHost
{
/// <summary>
/// Gets the data templates for the element.
/// </summary>
DataTemplates DataTemplates { get; }
/// <summary>
/// Gets a value indicating whether <see cref="DataTemplates"/> is initialized.
/// </summary>
/// <remarks>
/// The <see cref="DataTemplates"/> property may be lazily initialized, if so this property
/// indicates whether it has been initialized.
/// </remarks>
bool IsDataTemplatesInitialized { get; }
}
}

2
src/Avalonia.Diagnostics/DevTools.xaml.cs

@ -71,7 +71,7 @@ namespace Avalonia.Diagnostics
Width = 1024,
Height = 512,
Content = devTools,
DataTemplates = new DataTemplates
DataTemplates =
{
new ViewLocator<ViewModelBase>(),
}

2
src/Avalonia.Diagnostics/Views/ControlDetailsView.cs

@ -42,7 +42,7 @@ namespace Avalonia.Diagnostics.Views
{
Content = _grid = new SimpleGrid
{
Styles = new Styles
Styles =
{
new Style(x => x.Is<Control>())
{

20
src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj

@ -3,24 +3,8 @@
<TargetFramework>netcoreapp1.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NETSTANDARD</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Avalonia.DotNetCoreRuntime.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETSTANDARD</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Avalonia.DotNetCoreRuntime.XML</DocumentationFile>
<PropertyGroup>
<DocumentationFile>bin\$(Configuration)\Avalonia.DotNetCoreRuntime.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Shared\SharedAssemblyInfo.cs">

13
src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs

@ -59,7 +59,11 @@ namespace Avalonia
from attribute in assembly.GetCustomAttributes<ExportWindowingSubsystemAttribute>()
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<ExportRenderingSubsystemAttribute>()
@ -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),

3
src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj

@ -44,6 +44,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="AppBuilder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RuntimeInfo.cs" />

21
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")]

20
src/Avalonia.Interactivity/Interactive.cs

@ -16,14 +16,18 @@ namespace Avalonia.Interactivity
/// </summary>
public class Interactive : Layoutable, IInteractive
{
private readonly Dictionary<RoutedEvent, List<EventSubscription>> _eventHandlers =
new Dictionary<RoutedEvent, List<EventSubscription>>();
private Dictionary<RoutedEvent, List<EventSubscription>> _eventHandlers;
/// <summary>
/// Gets the interactive parent of the object for bubbling and tunnelling events.
/// </summary>
IInteractive IInteractive.InteractiveParent => ((IVisual)this).VisualParent as IInteractive;
private Dictionary<RoutedEvent, List<EventSubscription>> EventHandlers
{
get { return _eventHandlers ?? (_eventHandlers = new Dictionary<RoutedEvent, List<EventSubscription>>()); }
}
/// <summary>
/// Adds a handler for the specified routed event.
/// </summary>
@ -43,10 +47,10 @@ namespace Avalonia.Interactivity
List<EventSubscription> subscriptions;
if (!_eventHandlers.TryGetValue(routedEvent, out subscriptions))
if (!EventHandlers.TryGetValue(routedEvent, out subscriptions))
{
subscriptions = new List<EventSubscription>();
_eventHandlers.Add(routedEvent, subscriptions);
EventHandlers.Add(routedEvent, subscriptions);
}
var sub = new EventSubscription
@ -89,9 +93,9 @@ namespace Avalonia.Interactivity
Contract.Requires<ArgumentNullException>(routedEvent != null);
Contract.Requires<ArgumentNullException>(handler != null);
List<EventSubscription> subscriptions;
List<EventSubscription> 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<EventSubscription> subscriptions;
List<EventSubscription> subscriptions = null;
if (_eventHandlers.TryGetValue(e.RoutedEvent, out subscriptions))
if (_eventHandlers?.TryGetValue(e.RoutedEvent, out subscriptions) == true)
{
foreach (var sub in subscriptions.ToList())
{

3
src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj

@ -23,6 +23,9 @@
<DocumentationFile>bin\Release\Avalonia.Logging.Serilog.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Shared\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
</ItemGroup>

27
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")]

1
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@ -25,6 +25,7 @@
<None Remove="Shims.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Shared\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

24
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")]

12
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
{
/// <summary>
@ -8,6 +10,15 @@ namespace Avalonia.Styling
/// </summary>
public interface IStyleHost
{
/// <summary>
/// Gets a value indicating whether <see cref="Styles"/> is initialized.
/// </summary>
/// <remarks>
/// The <see cref="Styles"/> property may be lazily initialized, if so this property
/// indicates whether it has been initialized.
/// </remarks>
bool IsStylesInitialized { get; }
/// <summary>
/// Gets the styles for the element.
/// </summary>
@ -17,6 +28,5 @@ namespace Avalonia.Styling
/// Gets the parent style host element.
/// </summary>
IStyleHost StylingParent { get; }
}
}

11
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;

5
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);
}
}
}
}

2
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;

3
src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj

@ -47,6 +47,9 @@
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="CairoPlatform.cs" />
<Compile Include="Media\DrawingContext.cs" />
<Compile Include="Media\FormattedTextImpl.cs" />

20
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")]

3
src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj

@ -39,6 +39,9 @@
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="ClipboardImpl.cs" />
<Compile Include="EmbeddableImpl.cs" />
<Compile Include="Embedding\GtkAvaloniaControlHost.cs" />

13
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))]

1
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@ -24,6 +24,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
<Compile Include="..\Avalonia.Gtk\KeyTransform.cs">
<Link>KeyTransform.cs</Link>
</Compile>

2
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];

25
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))]

12
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;
}

10
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;
}
}

2
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(

2
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();

6
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);
}
}

6
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<object>();
target.Bind(Class1.FooProperty, source);
source.OnNext("initial");
source.OnNext(new BindingNotification(new InvalidOperationException("Foo"), BindingErrorType.Error));
source.OnNext(new BindingNotification(new InvalidOperationException("Foo"), BindingErrorType.DataValidationError));
Assert.Equal("initial", target.GetValue(Class1.FooProperty));
}
@ -389,7 +389,7 @@ namespace Avalonia.Base.UnitTests
LogCallback checkLogMessage = (level, area, src, mt, pv) =>
{
if (level == LogEventLevel.Error &&
if (level == LogEventLevel.Warning &&
area == LogArea.Binding &&
mt == "Error in binding to {Target}.{Property}: {Message}" &&
pv.Length == 3 &&

125
tests/Avalonia.Controls.UnitTests/ButtonTests.cs

@ -0,0 +1,125 @@
using System;
using System.Windows.Input;
using Avalonia.Markup.Xaml.Data;
using Xunit;
namespace Avalonia.Controls.UnitTests
{
public class ButtonTests
{
[Fact]
public void Button_Is_Disabled_When_Command_Is_Disabled()
{
var command = new TestCommand(false);
var target = new Button
{
Command = command,
};
Assert.False(target.IsEnabled);
command.IsEnabled = true;
Assert.True(target.IsEnabled);
command.IsEnabled = false;
Assert.False(target.IsEnabled);
}
[Fact]
public void Button_Is_Disabled_When_Bound_Command_Doesnt_Exist()
{
var target = new Button
{
[!Button.CommandProperty] = new Binding("Command"),
};
Assert.False(target.IsEnabled);
}
[Fact]
public void Button_Is_Disabled_When_Bound_Command_Is_Removed()
{
var viewModel = new
{
Command = new TestCommand(true),
};
var target = new Button
{
DataContext = viewModel,
[!Button.CommandProperty] = new Binding("Command"),
};
Assert.True(target.IsEnabled);
target.DataContext = null;
Assert.False(target.IsEnabled);
}
[Fact]
public void Button_Is_Enabled_When_Bound_Command_Is_Added()
{
var viewModel = new
{
Command = new TestCommand(true),
};
var target = new Button
{
DataContext = new object(),
[!Button.CommandProperty] = new Binding("Command"),
};
Assert.False(target.IsEnabled);
target.DataContext = viewModel;
Assert.True(target.IsEnabled);
}
[Fact]
public void Button_Is_Disabled_When_Disabled_Bound_Command_Is_Added()
{
var viewModel = new
{
Command = new TestCommand(false),
};
var target = new Button
{
DataContext = new object(),
[!Button.CommandProperty] = new Binding("Command"),
};
Assert.False(target.IsEnabled);
target.DataContext = viewModel;
Assert.False(target.IsEnabled);
}
private class TestCommand : ICommand
{
private bool _enabled;
public TestCommand(bool enabled)
{
_enabled = enabled;
}
public bool IsEnabled
{
get { return _enabled; }
set
{
if (_enabled != value)
{
_enabled = value;
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => _enabled;
public void Execute(object parameter)
{
}
}
}
}

2
tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs

@ -388,7 +388,7 @@ namespace Avalonia.Controls.UnitTests
{
Template = GetTemplate(),
DataContext = "Base",
DataTemplates = new DataTemplates
DataTemplates =
{
new FuncDataTemplate<Item>(x => new Button { Content = x })
},

8
tests/Avalonia.Controls.UnitTests/ListBoxTests.cs

@ -109,10 +109,10 @@ namespace Avalonia.Controls.UnitTests
{
Template = ListBoxTemplate(),
DataContext = "Base",
DataTemplates = new DataTemplates
{
new FuncDataTemplate<Item>(x => new Button { Content = x })
},
DataTemplates =
{
new FuncDataTemplate<Item>(x => new Button { Content = x })
},
Items = items,
};

2
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Unrooted.cs

@ -88,7 +88,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
root.Child = null;
root = new TestRoot
{
DataTemplates = new DataTemplates
DataTemplates =
{
new FuncDataTemplate<string>(x => new Decorator()),
},

1
tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

@ -265,6 +265,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
};
var globalStyles = new Mock<IGlobalStyles>();
globalStyles.Setup(x => x.IsStylesInitialized).Returns(true);
globalStyles.Setup(x => x.Styles).Returns(styles);
var renderInterface = new Mock<IPlatformRenderInterface>();

8
tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs

@ -399,7 +399,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
TestTemplatedControl target;
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TestTemplatedControl>())
{
@ -435,7 +435,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
TestTemplatedControl target;
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TestTemplatedControl>())
{
@ -474,7 +474,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TestTemplatedControl>())
{
@ -494,7 +494,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
var root2 = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TestTemplatedControl>())
{

4
tests/Avalonia.Controls.UnitTests/TabControlTests.cs

@ -135,7 +135,7 @@ namespace Avalonia.Controls.UnitTests
{
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TabItem>())
{
@ -174,7 +174,7 @@ namespace Avalonia.Controls.UnitTests
{
Template = new FuncControlTemplate<TabControl>(CreateTabControlTemplate),
DataContext = "Base",
DataTemplates = new DataTemplates
DataTemplates =
{
new FuncDataTemplate<Item>(x => new Button { Content = x })
},

28
tests/Avalonia.Controls.UnitTests/TreeViewTests.cs

@ -25,9 +25,9 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTreeViewTemplate(),
Items = CreateTestTreeData(),
DataTemplates = CreateNodeDataTemplate(),
};
CreateNodeDataTemplate(target);
ApplyTemplates(target);
Assert.Equal(new[] { "Root" }, ExtractItemHeader(target, 0));
@ -69,9 +69,9 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTreeViewTemplate(),
Items = CreateTestTreeData(),
DataTemplates = CreateNodeDataTemplate(),
};
CreateNodeDataTemplate(target);
ApplyTemplates(target);
var container = (TreeViewItem)target.ItemContainerGenerator.Containers.Single().ContainerControl;
@ -87,7 +87,6 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTreeViewTemplate(),
Items = tree,
DataTemplates = CreateNodeDataTemplate(),
};
// For TreeViewItem to find its parent TreeView, OnAttachedToLogicalTree needs
@ -95,6 +94,7 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot();
root.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target);
var container = target.ItemContainerGenerator.Index.ContainerFromItem(
@ -116,11 +116,12 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTreeViewTemplate(),
Items = tree,
DataTemplates = CreateNodeDataTemplate(),
};
var visualRoot = new TestRoot();
visualRoot.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target);
var item = tree[0].Children[1].Children[0];
@ -146,11 +147,12 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTreeViewTemplate(),
Items = tree,
DataTemplates = CreateNodeDataTemplate(),
};
var visualRoot = new TestRoot();
visualRoot.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target);
var item = tree[0].Children[1].Children[0];
@ -191,12 +193,13 @@ namespace Avalonia.Controls.UnitTests
var target = new TreeView
{
Template = CreateTreeViewTemplate(),
DataTemplates = CreateNodeDataTemplate(),
Items = tree,
};
var root = new TestRoot();
root.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target);
Assert.Equal(5, target.ItemContainerGenerator.Index.Items.Count());
@ -221,7 +224,7 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTreeViewTemplate(),
DataContext = "Base",
DataTemplates = new DataTemplates
DataTemplates =
{
new FuncDataTemplate<Node>(x => new Button { Content = x })
},
@ -291,9 +294,9 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTreeViewTemplate(),
Items = data,
DataTemplates = CreateNodeDataTemplate(),
};
CreateNodeDataTemplate(target);
ApplyTemplates(target);
Assert.Equal(new[] { "Root" }, ExtractItemHeader(target, 0));
@ -328,7 +331,6 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTreeViewTemplate(),
Items = data,
DataTemplates = CreateNodeDataTemplate(),
};
var button = new Button();
@ -341,6 +343,7 @@ namespace Avalonia.Controls.UnitTests
}
};
CreateNodeDataTemplate(target);
ApplyTemplates(target);
var item = data[0].Children[0];
@ -411,12 +414,9 @@ namespace Avalonia.Controls.UnitTests
};
}
private DataTemplates CreateNodeDataTemplate()
private void CreateNodeDataTemplate(IControl control)
{
return new DataTemplates
{
new TestTreeDataTemplate()
};
control.DataTemplates.Add(new TestTreeDataTemplate());
}
private IControlTemplate CreateTreeViewTemplate()

2
tests/Avalonia.Controls.UnitTests/UserControlTests.cs

@ -21,7 +21,7 @@ namespace Avalonia.Controls.UnitTests
var target = new UserControl();
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<ContentControl>())
{

6
tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj

@ -19,4 +19,8 @@
<ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj" />
<ProjectReference Include="..\Avalonia.UnitTests\Avalonia.UnitTests.csproj" />
</ItemGroup>
</Project>
</Project>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
</Project>

1
tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs

@ -193,6 +193,7 @@ namespace Avalonia.Layout.UnitTests
.Bind<IWindowingPlatform>().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);
}
}

2
tests/Avalonia.LeakTests/ControlTests.cs

@ -276,7 +276,7 @@ namespace Avalonia.LeakTests
{
Content = target = new TreeView
{
DataTemplates = new DataTemplates
DataTemplates =
{
new FuncTreeDataTemplate<Node>(
x => new TextBlock { Text = x.Name },

55
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<object>();
var sub = target.Subscribe(x => result.Add(x));
var sub = target.Subscribe(x => result.Add(x));
Assert.Equal(new[] { "foo" }, result);
@ -305,7 +325,7 @@ namespace Avalonia.Markup.UnitTests.Data
data.Next = old;
Assert.Equal(
new object[]
new object[]
{
"bar",
new BindingNotification(
@ -313,7 +333,7 @@ namespace Avalonia.Markup.UnitTests.Data
BindingErrorType.Error,
AvaloniaProperty.UnsetValue),
"bar"
},
},
result);
sub.Dispose();
@ -473,7 +493,7 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact]
public void SetValue_Should_Return_False_For_Missing_Property()
{
var data = new Class1 { Next = new WithoutBar()};
var data = new Class1 { Next = new WithoutBar() };
var target = new ExpressionObserver(data, "Next.Bar");
using (target.Subscribe(_ => { }))
@ -545,12 +565,15 @@ namespace Avalonia.Markup.UnitTests.Data
update.OnNext(Unit.Default);
Assert.Equal(
new object[]
new object[]
{
"foo",
"bar",
AvaloniaProperty.UnsetValue,
},
new BindingNotification(
new MarkupBindingChainException("Null value", "Foo", string.Empty),
BindingErrorType.Error,
AvaloniaProperty.UnsetValue)
},
result);
Assert.Equal(0, first.PropertyChangedSubscriptionCount);

4
tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs

@ -302,12 +302,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data
// Bind Foo and Bar to the VM.
target.Bind(OldDataContextTest.FooProperty, fooBinding);
//target.Bind(OldDataContextTest.BarProperty, barBinding);
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));
Assert.Equal(2, target.GetValue(OldDataContextTest.BarProperty));
// Set DataContext to null.
target.DataContext = null;

2
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlBindingTests.cs

@ -37,7 +37,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
LogCallback checkLogMessage = (level, area, src, mt, pv) =>
{
if (level == LogEventLevel.Error &&
if (level == LogEventLevel.Warning &&
area == LogArea.Binding &&
mt == "Error in binding to {Target}.{Property}: {Message}" &&
pv.Length == 3 &&

20
tests/Avalonia.Styling.UnitTests/ResourceTests.cs

@ -16,7 +16,7 @@ namespace Avalonia.Styling.UnitTests
var tree = new Decorator
{
Styles = new Styles
Styles =
{
new Style
{
@ -29,7 +29,7 @@ namespace Avalonia.Styling.UnitTests
},
Child = target = new Border
{
Styles = new Styles
Styles =
{
new Style
{
@ -60,16 +60,16 @@ namespace Avalonia.Styling.UnitTests
var tree = target = new Border
{
Styles = new Styles
Styles =
{
new Style
{
new Style
Resources = new StyleResources
{
Resources = new StyleResources
{
{ "Foo", "foo" },
}
},
}
{ "Foo", "foo" },
}
},
}
};
Assert.Equal(AvaloniaProperty.UnsetValue, target.FindStyleResource("Baz"));

4
tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs

@ -74,6 +74,10 @@ namespace Avalonia.Visuals.UnitTests.Media
" M 16.6309 19.9063C 21.6309 24.1563 25.1309 26.1562 31.6309 28.6562C 31.6309 28.6562 26.3809 39.1562 18" +
".3809 36.1563C 18.3809 36.1563 18 38 16.3809 36.9063C 15 36 16.3809 34.9063 16.3809 34.9063C 16.3809 34" +
".9063 10.1309 30.9062 16.6309 19.9063 Z ")]
[InlineData(
"F1M16,12C16,14.209 14.209,16 12,16 9.791,16 8,14.209 8,12 8,11.817 8.03,11.644 8.054,11.467L6.585,10 4,10 " +
"4,6.414 2.5,7.914 0,5.414 0,3.586 3.586,0 4.414,0 7.414,3 7.586,3 9,1.586 11.914,4.5 10.414,6 " +
"12.461,8.046C14.45,8.278,16,9.949,16,12")]
public void Should_Parse(string pathData)
{
using (AvaloniaLocator.EnterScope())

Loading…
Cancel
Save