MahApps / MahApps/MahApps.Metro
Validation error popup on TextBox briefly flashes at the top of screen
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 9.8k
- Forks
- 2.4k
- Avg merge
- 1h 2m
- Merged PRs (30d)
- 56
Description
Describe the bug
When using data validation against a user-entered value via a TextBox with UpdateSourceTrigger=PropertyChanged, I have noticed that whenever the user enters an incorrect value, the error popup will actually appear briefly at the top of the screen before returning to the correct place besides the offending TextBox.
This looks extremely similar, if not identical, to #4120. But confusingly, I get the same behaviour even if I remove ValidatesOnExceptions=True.
Another issue, #3809, which is for a different bug, however there was a screenshot included in the replies that perfectly demonstrates what is occurring for me. However, here is a video recorded from my machine. This occurs when running in Debug and Release.
https://github.com/MahApps/MahApps.Metro/assets/42159320/1057965a-e999-4930-a445-469c81996316
Steps to reproduce
- Have a model for data validation that implements
INotifyDataErrorInfo:
public abstract class ValidationModelBase : INotifyDataErrorInfo
{
private readonly IDictionary<string, List<string>> propertyErrors;
protected ValidationModelBase()
{
this.propertyErrors = new Dictionary<string, List<string>>();
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public bool HasErrors => this.propertyErrors.Any();
public bool IsValid => !this.HasErrors;
public IEnumerable GetErrors(string propertyName)
{
if (propertyName == null)
{
return null;
}
return this.propertyErrors.TryGetValue(propertyName, out List<string> errors) ? errors : null;
}
public void AddErrors(string propertyName, string message)
{
if (!this.propertyErrors.ContainsKey(propertyName))
{
this.propertyErrors.Add(propertyName, new List<string>());
}
this.propertyErrors[propertyName].Add(message);
this.RaiseErrorsChangedEvent(propertyName);
}
public void RemoveErrors(string propertyName)
{
if (this.propertyErrors.Remove(propertyName))
{
this.RaiseErrorsChangedEvent(propertyName);
}
}
private void RaiseErrorsChangedEvent(string propertyName)
{
this.ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
}
}
public class Router : ValidationModelBase
{
private string routerIpv4Address;
public string RouterIpv4Address
{
get => this.routerIpv4Address;
set
{
if (value != this.routerIpv4Address)
{
this.RemoveErrors(nameof(this.RouterIpv4Address));
if (!NetworkService.VerifyIpv4Address(value)) // hardcode true/false here to mimic actual verification for the purpose of duplication
{
this.AddErrors(nameof(this.RouterIpv4Address), "Not a valid IPv4 value");
}
this.routerIpv4Address = value;
}
}
}
}
- Use this model as the backing field for a property you intend to validate inside a ViewModel:
public class RouterSetupViewModel : ObservableObject, INotifyDataErrorInfo
{
private readonly Router router;
public RouterSetupViewModel()
{
this.router = new Router();
this.router.ErrorsChanged += this.RouterErrorsChanged;
}
public bool HasErrors => this.router.HasErrors;
public IEnumerable GetErrors(string propertyName)
{
return this.router.GetErrors(propertyName);
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public string RouterIpv4Address
{
get => this.router.RouterIpv4Address;
set {
this.router.RouterIpv4Address = value;
this.OnPropertyChanged();
}
}
private void RouterErrorsChanged(object sender, DataErrorsChangedEventArgs e)
{
this.ErrorsChanged?.Invoke(this, e);
}
}
- Bind to property in view:
<TextBox
Text="{ Binding RouterIpv4Address,
UpdateSourceTrigger=PropertyChanged,
NotifyOnValidationError=True,
ValidatesOnExceptions=True,
Delay=400}"
mah:TextBoxHelper.ClearTextButton="True"
mah:TextBoxHelper.UseFloatingWatermark="True"
mah:TextBoxHelper.Watermark="Router's IP address"/>
Expected behavior
The error only appears alongside the TextBox.
Actual behavior
The error briefly flashes at the top of the screen.
Environment
MahApps.Metro version: 2.4.9
Windows build number: Win11 22H2 [Version 22621.1778]
Visual Studio Enterprise 2022 17.6.2
Target Framework: .NET Framework 4.8
Screenshots
Video included above.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the supplied TextBox validation binding with INotifyDataErrorInfo on the stated .NET Framework 4.8 and Windows environment, then trace the validation error popup's positioning relative to the offending TextBox. Done means the error remains alongside the TextBox without briefly appearing at the top of the screen in both Debug and Release.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- desktop, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100