Validation WIP

This commit is contained in:
2023-04-12 17:14:12 -04:00
parent 68aec56824
commit ace251fd4f
6 changed files with 158 additions and 67 deletions

View File

@@ -1,9 +1,10 @@
using Realms; using System;
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using Realms;
namespace FeedCenter namespace FeedCenter
{ {
@@ -11,13 +12,21 @@ namespace FeedCenter
{ {
public const string DefaultName = "< default >"; public const string DefaultName = "< default >";
private readonly Dictionary<string, List<string>> _errorsByPropertyName = new(); private readonly DataErrorDictionary _dataErrorDictionary;
public Category()
{
_dataErrorDictionary = new DataErrorDictionary();
_dataErrorDictionary.ErrorsChanged += DataErrorDictionaryErrorsChanged;
}
[Ignored]
public ICollection<Feed> Feeds { get; set; }
[PrimaryKey] [PrimaryKey]
public Guid Id { get; set; } = Guid.NewGuid(); public Guid Id { get; set; } = Guid.NewGuid();
[MapTo("Name")] public bool IsDefault { get; internal set; }
private string RawName { get; set; } = string.Empty;
public string Name public string Name
{ {
@@ -31,60 +40,37 @@ namespace FeedCenter
} }
} }
[Ignored] [MapTo("Name")]
public ICollection<Feed> Feeds { get; set; } private string RawName { get; set; } = string.Empty;
[UsedImplicitly]
public int SortKey => IsDefault ? 0 : 1;
public bool HasErrors => _dataErrorDictionary.Any();
public IEnumerable GetErrors(string propertyName)
{
return _dataErrorDictionary.GetErrors(propertyName);
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
private void DataErrorDictionaryErrorsChanged(object sender, DataErrorsChangedEventArgs e)
{
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(e.PropertyName));
}
public static Category CreateDefault() public static Category CreateDefault()
{ {
return new Category { Name = DefaultName, IsDefault = true }; return new Category { Name = DefaultName, IsDefault = true };
} }
public bool IsDefault { get; internal set; }
// ReSharper disable once UnusedMember.Global
public int SortKey => IsDefault ? 0 : 1;
public bool HasErrors => _errorsByPropertyName.Any();
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public IEnumerable GetErrors(string propertyName)
{
return _errorsByPropertyName.TryGetValue(propertyName, out var value) ? value : null;
}
private void OnErrorsChanged(string propertyName)
{
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
}
private void ValidateName() private void ValidateName()
{ {
ClearErrors(nameof(Name)); _dataErrorDictionary.ClearErrors(nameof(Name));
if (string.IsNullOrWhiteSpace(Name)) if (string.IsNullOrWhiteSpace(Name))
AddError(nameof(Name), "Name cannot be empty"); _dataErrorDictionary.AddError(nameof(Name), "Name cannot be empty");
}
private void AddError(string propertyName, string error)
{
if (!_errorsByPropertyName.ContainsKey(propertyName))
_errorsByPropertyName[propertyName] = new List<string>();
if (_errorsByPropertyName[propertyName].Contains(error))
return;
_errorsByPropertyName[propertyName].Add(error);
OnErrorsChanged(propertyName);
}
private void ClearErrors(string propertyName)
{
if (!_errorsByPropertyName.ContainsKey(propertyName))
return;
_errorsByPropertyName.Remove(propertyName);
OnErrorsChanged(propertyName);
} }
} }
} }

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
namespace FeedCenter
{
internal class DataErrorDictionary : Dictionary<string, List<string>>
{
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
private void OnErrorsChanged(string propertyName)
{
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
}
public IEnumerable GetErrors(string propertyName)
{
return TryGetValue(propertyName, out var value) ? value : null;
}
public void AddError(string propertyName, string error)
{
if (!ContainsKey(propertyName))
this[propertyName] = new List<string>();
if (this[propertyName].Contains(error))
return;
this[propertyName].Add(error);
OnErrorsChanged(propertyName);
}
public void ClearErrors(string propertyName)
{
if (!ContainsKey(propertyName))
return;
Remove(propertyName);
OnErrorsChanged(propertyName);
}
}
}

View File

@@ -1,5 +1,15 @@
using System; using ChrisKaczor.ApplicationUpdate;
using FeedCenter.Data;
using FeedCenter.FeedParsers;
using FeedCenter.Properties;
using FeedCenter.Xml;
using JetBrains.Annotations;
using Realms;
using Serilog;
using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -9,14 +19,6 @@ using System.Net.Http.Headers;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using ChrisKaczor.ApplicationUpdate;
using FeedCenter.Data;
using FeedCenter.FeedParsers;
using FeedCenter.Properties;
using FeedCenter.Xml;
using JetBrains.Annotations;
using Realms;
using Serilog;
namespace FeedCenter namespace FeedCenter
{ {
@@ -55,9 +57,18 @@ namespace FeedCenter
#endregion #endregion
public partial class Feed : RealmObject public partial class Feed : RealmObject, INotifyDataErrorInfo
{ {
private static HttpClient _httpClient; private static HttpClient _httpClient;
private readonly DataErrorDictionary _dataErrorDictionary;
public Feed()
{
_dataErrorDictionary = new DataErrorDictionary();
_dataErrorDictionary.ErrorsChanged += DataErrorDictionaryErrorsChanged;
}
public bool Authenticate { get; set; } public bool Authenticate { get; set; }
public Guid CategoryId { get; set; } public Guid CategoryId { get; set; }
@@ -112,17 +123,68 @@ namespace FeedCenter
private string MultipleOpenActionRaw { get; set; } private string MultipleOpenActionRaw { get; set; }
public string Name { get; set; } public string Name
{
get => RawName;
set
{
RawName = value;
ValidateString(nameof(Name), RawName);
RaisePropertyChanged();
}
}
public string Password { get; set; } public string Password { get; set; }
public string Source { get; set; }
[MapTo("Name")]
private string RawName { get; set; } = string.Empty;
[MapTo("Source")]
private string RawSource { get; set; } = string.Empty;
public string Source
{
get => RawSource;
set
{
RawSource = value;
ValidateString(nameof(Source), RawSource);
RaisePropertyChanged();
}
}
public string Title { get; set; } public string Title { get; set; }
public string Username { get; set; } public string Username { get; set; }
public bool HasErrors => _dataErrorDictionary.Any();
public IEnumerable GetErrors(string propertyName)
{
return _dataErrorDictionary.GetErrors(propertyName);
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public static Feed Create() public static Feed Create()
{ {
return new Feed { Id = Guid.NewGuid(), CategoryId = Database.Entities.DefaultCategory.Id }; return new Feed { Id = Guid.NewGuid(), CategoryId = Database.Entities.DefaultCategory.Id };
} }
private void DataErrorDictionaryErrorsChanged(object sender, DataErrorsChangedEventArgs e)
{
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(e.PropertyName));
}
private void ValidateString(string propertyName, string value)
{
_dataErrorDictionary.ClearErrors(propertyName);
if (string.IsNullOrWhiteSpace(value))
_dataErrorDictionary.AddError(propertyName, $"{propertyName} cannot be empty");
}
#region Reading #region Reading
public FeedReadResult Read(bool forceRead = false) public FeedReadResult Read(bool forceRead = false)

View File

@@ -34,7 +34,7 @@
Target="{Binding ElementName=NameTextBox}" /> Target="{Binding ElementName=NameTextBox}" />
<TextBox Name="NameTextBox" <TextBox Name="NameTextBox"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"> Text="{Binding Path=Name, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=True}">
</TextBox> </TextBox>
</StackPanel> </StackPanel>
<StackPanel <StackPanel

View File

@@ -1,5 +1,5 @@
using ChrisKaczor.Wpf.Validation; using System.Windows;
using System.Windows; using ChrisKaczor.Wpf.Validation;
using FeedCenter.Data; using FeedCenter.Data;
namespace FeedCenter.Options namespace FeedCenter.Options

View File

@@ -1,10 +1,10 @@
using ChrisKaczor.Wpf.Validation; using System.Linq;
using FeedCenter.Data;
using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Media; using System.Windows.Media;
using ChrisKaczor.Wpf.Validation;
using FeedCenter.Data;
namespace FeedCenter.Options namespace FeedCenter.Options
{ {