From aacb0522534a038449e4f3983e8af567e79fd24f Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Sat, 29 Apr 2017 21:20:26 -0500 Subject: [PATCH] Made changes requested by @grokys. --- Avalonia.sln | 5 +- src/Avalonia.Controls/Button.cs | 5 +- .../Data/ExpressionObserver.cs | 12 +- .../Avalonia.Controls.UnitTests.csproj | 1 + .../ButtonTests.cs | 125 ++++++++++++++++++ 5 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 tests/Avalonia.Controls.UnitTests/ButtonTests.cs diff --git a/Avalonia.sln b/Avalonia.sln index 3ab8048857..c243e1bae0 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26403.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Base", "src\Avalonia.Base\Avalonia.Base.csproj", "{B09B78D8-9B26-48B0-9149-D64A2F120F3F}" EndProject @@ -176,6 +176,7 @@ Global tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{48840edd-24bf-495d-911e-2eb12ae75d3b}*SharedItemsImports = 13 src\Shared\PlatformSupport\PlatformSupport.projitems*{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}*SharedItemsImports = 4 src\Shared\PlatformSupport\PlatformSupport.projitems*{7863ea94-f0fb-4386-bf8c-e5bfa761560a}*SharedItemsImports = 4 + src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 4 src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 4 src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 4 src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{811a76cf-1cf6-440f-963b-bbe31bd72a82}*SharedItemsImports = 4 diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index 5d878e87cb..28c3a2e4ca 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -249,7 +249,10 @@ namespace Avalonia.Controls base.UpdateDataValidation(property, status); if(property == CommandProperty) { - IsEnabled = status?.ErrorType != BindingErrorType.Error; + if(status?.ErrorType == BindingErrorType.Error) + { + IsEnabled = false; + } } } 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/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj index aea972ec42..969e25167e 100644 --- a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj +++ b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj @@ -95,6 +95,7 @@ + diff --git a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs new file mode 100644 index 0000000000..71bf9104f7 --- /dev/null +++ b/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) + { + } + } + } +} \ No newline at end of file