WPF - validation adorners do not position correctly when there multiple controls with validation errors

32 views Asked by At

I have a WPF application built with .NET Framework 4.8. I have a viewmodel that implements INotifyDataErrorInfo for validation. In my XAML I am using the default Validation.ErrorTemplate, but I have also tried using a custom template with the same results.

If I only have a few controls with validation errors, the default WPF validation adorners appear correctly. If have a lot of controls with validation errors the adorners do not always appear around the AdornedElement.

Here is a sample application that demonstrates the issue:

ViewModel.cs

public  class ViewModel: INotifyPropertyChanged, INotifyDataErrorInfo
{
    private string _value;

    public string Value
    {
        get { return _value; }
        set
        {
            _value = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public IEnumerable GetErrors(string propertyName)
    {
        return new[]{"Value cannot be null"};
    }

    public bool HasErrors
    {
        get
        {
            return string.IsNullOrEmpty(_value);
        }
    }

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
    
}

MainWindow.xaml <

Window x:Class="ValidationErrorProblem.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ValidationErrorProblem"
        mc:Ignorable="d"
        Title="MainWindow" Height="800" Width="400">
    <Grid>
        <ScrollViewer HorizontalAlignment="Right">
            <ItemsControl x:Name="MyList">
                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="{x:Type local:ViewModel}">
                        <TextBox Margin="5" Text="{Binding Value}" Width="100"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </Grid>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var items = new List<ViewModel>();
        for (var i = 0; i < 200; i++) items.Add(new ViewModel());
        MyList.ItemsSource = items;
    }
}

Here is what it looks like when run the application and start scrolling: enter image description here

If I resize the window after I scroll, it temporarily fixes the adorner placements. But as soon as I scroll again, I get the same problem.

I can fix this if I wrap the TextBox in its own AdornerDecorator. But my actual application contains multiple UserControls that each have hundreds of unique controls (TextBoxes, ComboBoxes, ToggleButtons, etc) that are not created from a template. I do not want to have to update my XAML to add more AdornerDecorators, especially not one for each control.

This seems like a bug in .Net Framework (4.8). Does anyone else have this problem, and have you found a simple fix?

0

There are 0 answers