Ghost1372

everything can be handy

Validation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<Grid>
<Grid.Resources>
<DataTemplate x:Key="ValidationTemplate" x:DataType="x:String">
<TextBlock Foreground="{ThemeResource SystemFillColorCriticalBrush}" Text="{x:Bind}" />
</DataTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Spacing="6">
<TextBox
x:Name="NameBox"
wuc:Validation.ErrorTemplate="{StaticResource ValidationTemplate}"
wuc:Validation.ValidationPropertyName="Name"
wuc:Validation.ValidationProvider="{x:Bind UserInfo}"
Header="Easy boxes with validation"
PlaceholderText="Name"
Style="{StaticResource ValidatingTextBoxStyle}"
Text="{x:Bind UserInfo.Name, Mode=TwoWay}" />

<TextBox
x:Name="MailBox"
wuc:Validation.ErrorTemplate="{StaticResource ValidationTemplate}"
wuc:Validation.ValidationPropertyName="Mail"
wuc:Validation.ValidationProvider="{x:Bind UserInfo}"
PlaceholderText="Mail"
Style="{StaticResource ValidatingTextBoxStyle}"
Text="{x:Bind UserInfo.Mail, Mode=TwoWay}" />

<Button
x:Name="CoolButton"
Width="320"
HorizontalAlignment="Center"
Click="CoolButton_Click"
Content="Cool button"
IsEnabled="{x:Bind UserInfo.HasErrors.Equals(x:False), Mode=OneWay}"
Style="{StaticResource AccentButtonStyle}" />
</StackPanel>

<Frame Name="frame" Grid.Column="1"/>
</Grid>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
public sealed class UserInfo : INotifyDataErrorInfo, INotifyPropertyChanged
{
public UserInfo()
{
ValidateName(_name);
ValidateMail(_mail);
}

public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new(propertyName));

private string _name = string.Empty;
public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
ValidateName(_name);
OnPropertyChanged();
}
}
}

private string _mail = string.Empty;
public string Mail
{
get => _mail;
set
{
if (_mail != value)
{
_mail = value;
ValidateMail(_mail);
OnPropertyChanged();
}
}
}

private void ValidateName(string name)
{
var errors = new List<string>(3);
if (name.Contains("1", StringComparison.InvariantCulture))
errors.Add("Using Jungkook's favorite number is not allowed.");

if (name.Length == 0)
errors.Add("You'll need a name. I will not accept this.");
else if (name.Length > 4)
errors.Add("Your name is too long. Make it shorter.");

if (name.Contains("LPK", StringComparison.InvariantCultureIgnoreCase))
errors.Add("Name is forbidden for unknown reasons.");

SetErrors("Name", errors);
}

private void ValidateMail(string mail)
{
var errors = new List<string>(2);
if (mail.Contains("1", StringComparison.InvariantCulture))
errors.Add("Using Jungkook's favorite number is not allowed.");

if (!mail.Contains("@", StringComparison.InvariantCultureIgnoreCase))
errors.Add("Invalid mail.");

SetErrors("Mail", errors);
}

// Error validation
private readonly Dictionary<string, ICollection<string>> _validationErrors = new();

public bool HasErrors => _validationErrors.Count > 0;

public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
private void OnErrorsChanged(string propertyName)
{
ErrorsChanged?.Invoke(this, new(propertyName));
OnPropertyChanged(nameof(HasErrors));
}

public IEnumerable GetErrors(string propertyName)
{
if (string.IsNullOrEmpty(propertyName) ||
!_validationErrors.ContainsKey(propertyName))
return null;

return _validationErrors[propertyName];
}

private void SetErrors(string key, ICollection<string> errors)
{
if (errors.Any())
_validationErrors[key] = errors;
else
_ = _validationErrors.Remove(key);

OnErrorsChanged(key);
}
}

and in MainWindow.xaml.cs

1
2
3
4
5
6
public UserInfo UserInfo { get; } = new();

private void CoolButton_Click(object sender, RoutedEventArgs e)
{
frame.Navigate(typeof(AccountPage));
}

DevWinUI

Demo

you can run demo and see this feature.

0%