Browse Source

Changed validation on controls to allow notifications from multiple types of validation and correctly report if it is valid. Changed initalization of validation plugins to nest within each other so there can be multiple active at once.

pull/514/head
Jeremy Koritzinsky 11 years ago
parent
commit
aab4331a52
  1. 10
      src/Markup/Perspex.Markup/Data/ExpressionNode.cs
  2. 8
      src/Markup/Perspex.Markup/Data/PropertyAccessorNode.cs
  3. 10
      src/Perspex.Controls/Control.cs
  4. 27
      src/Perspex.Controls/ControlValidationStatus.cs
  5. 1
      src/Perspex.Controls/Perspex.Controls.csproj
  6. 3
      tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj
  7. 9
      tests/Perspex.Markup.Xaml.UnitTests/Data/BindingTests_Validation.cs

10
src/Markup/Perspex.Markup/Data/ExpressionNode.cs

@ -107,7 +107,15 @@ namespace Perspex.Markup.Data
protected virtual void SendValidationStatus(ValidationStatus status) protected virtual void SendValidationStatus(ValidationStatus status)
{ {
_subject?.OnNext(status); //Even if elements only bound to sub-values, send validation changes along so they will be surfaced to the UI level.
if (_subject != null)
{
_subject.OnNext(status);
}
else
{
Next.SendValidationStatus(status);
}
} }
protected virtual void Unsubscribe(object target) protected virtual void Unsubscribe(object target)

8
src/Markup/Perspex.Markup/Data/PropertyAccessorNode.cs

@ -55,10 +55,12 @@ namespace Perspex.Markup.Data
if (accessorPlugin != null) if (accessorPlugin != null)
{ {
_accessor = accessorPlugin.Start(reference, PropertyName, SetCurrentValue); _accessor = accessorPlugin.Start(reference, PropertyName, SetCurrentValue);
var validationPlugin = ExpressionObserver.ValidationCheckers.FirstOrDefault(x => x.Match(reference)); foreach (var validationPlugin in ExpressionObserver.ValidationCheckers.Where(x => x.Match(reference)))
if (validationPlugin != null)
{ {
_accessor = validationPlugin.Start(reference, PropertyName, _accessor, SendValidationStatus); if (validationPlugin != null)
{
_accessor = validationPlugin.Start(reference, PropertyName, _accessor, SendValidationStatus);
}
} }
if (_accessor != null) if (_accessor != null)

10
src/Perspex.Controls/Control.cs

@ -89,8 +89,8 @@ namespace Perspex.Controls
/// <summary> /// <summary>
/// Defines the <see cref="ValidationStatus"/> property. /// Defines the <see cref="ValidationStatus"/> property.
/// </summary> /// </summary>
public static readonly DirectProperty<Control, ValidationStatus> ValidationStatusProperty = public static readonly DirectProperty<Control, ControlValidationStatus> ValidationStatusProperty =
PerspexProperty.RegisterDirect<Control, ValidationStatus>(nameof(ValidationStatus), c=> c.ValidationStatus); PerspexProperty.RegisterDirect<Control, ControlValidationStatus>(nameof(ValidationStatus), c=> c.ValidationStatus);
private int _initCount; private int _initCount;
private string _name; private string _name;
@ -406,12 +406,12 @@ namespace Perspex.Controls
/// </summary> /// </summary>
protected IPseudoClasses PseudoClasses => Classes; protected IPseudoClasses PseudoClasses => Classes;
private ValidationStatus validationStatus; private ControlValidationStatus validationStatus = new ControlValidationStatus();
/// <summary> /// <summary>
/// The current validation status of the control. /// The current validation status of the control.
/// </summary> /// </summary>
public ValidationStatus ValidationStatus public ControlValidationStatus ValidationStatus
{ {
get get
{ {
@ -427,7 +427,7 @@ namespace Perspex.Controls
protected override void DataValidation(PerspexProperty property, ValidationStatus status) protected override void DataValidation(PerspexProperty property, ValidationStatus status)
{ {
base.DataValidation(property, status); base.DataValidation(property, status);
ValidationStatus = status; ValidationStatus.UpdateValidationStatus(status);
} }
/// <summary> /// <summary>

27
src/Perspex.Controls/ControlValidationStatus.cs

@ -0,0 +1,27 @@
using Perspex.Data;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Perspex.Controls
{
public class ControlValidationStatus : ValidationStatus, INotifyPropertyChanged
{
private Dictionary<Type, ValidationStatus> propertyValidation = new Dictionary<Type, ValidationStatus>();
public override bool IsValid => propertyValidation.Values.All(status => status.IsValid);
public event PropertyChangedEventHandler PropertyChanged;
public override bool Match(ValidationMethods enabledMethods) => true;
public void UpdateValidationStatus(ValidationStatus status)
{
propertyValidation[status.GetType()] = status;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(""));
}
}
}

1
src/Perspex.Controls/Perspex.Controls.csproj

@ -46,6 +46,7 @@
<Compile Include="Application.cs" /> <Compile Include="Application.cs" />
<Compile Include="Classes.cs" /> <Compile Include="Classes.cs" />
<Compile Include="ContextMenu.cs" /> <Compile Include="ContextMenu.cs" />
<Compile Include="ControlValidationStatus.cs" />
<Compile Include="Design.cs" /> <Compile Include="Design.cs" />
<Compile Include="DockPanel.cs" /> <Compile Include="DockPanel.cs" />
<Compile Include="Expander.cs" /> <Compile Include="Expander.cs" />

3
tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj

@ -196,9 +196,6 @@
<ItemGroup> <ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<Choose> <Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup> <ItemGroup>

9
tests/Perspex.Markup.Xaml.UnitTests/Data/BindingTests_Validation.cs

@ -13,7 +13,6 @@ namespace Perspex.Markup.Xaml.UnitTests.Data
{ {
public class BindingTests_Validation public class BindingTests_Validation
{ {
public class Data : INotifyPropertyChanged public class Data : INotifyPropertyChanged
{ {
private string mustbeNonEmpty; private string mustbeNonEmpty;
@ -54,7 +53,7 @@ namespace Perspex.Markup.Xaml.UnitTests.Data
target.Text = ""; target.Text = "";
Assert.Null(target.ValidationStatus); Assert.True(target.ValidationStatus.IsValid);
} }
[Fact] [Fact]
@ -71,7 +70,7 @@ namespace Perspex.Markup.Xaml.UnitTests.Data
target.Bind(TextBlock.TextProperty, binding); target.Bind(TextBlock.TextProperty, binding);
target.Text = ""; target.Text = "";
Assert.NotNull(target.ValidationStatus); Assert.False(target.ValidationStatus.IsValid);
} }
[Fact] [Fact]
@ -89,7 +88,7 @@ namespace Perspex.Markup.Xaml.UnitTests.Data
target.Tag = ""; target.Tag = "";
Assert.Null(target.ValidationStatus); Assert.True(target.ValidationStatus.IsValid);
} }
[Fact] [Fact]
@ -106,7 +105,7 @@ namespace Perspex.Markup.Xaml.UnitTests.Data
target.Bind(Control.TagProperty, binding); target.Bind(Control.TagProperty, binding);
target.Tag = ""; target.Tag = "";
Assert.NotNull(target.ValidationStatus); Assert.False(target.ValidationStatus.IsValid);
} }
} }
} }

Loading…
Cancel
Save