You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Framework 4.8下WPF多验证错误控件装饰器定位异常

修复.NET Framework 4.8 WPF大量验证控件滚动时装饰器错位问题

问题原因

这是.NET Framework 4.8中WPF AdornerLayer的已知bug:当共享同一个AdornerLayer的大量元素滚动时,AdornerLayer无法正确跟踪元素的位置更新,导致验证装饰器(Validation.ErrorTemplate)错位。调整窗口大小会触发布局重计算,临时修复位置,但滚动时问题复现。

简便修复方案

不用逐个给控件包裹AdornerDecorator,有两种高效的批量处理方式:

1. 给ItemsControl的ItemTemplate统一添加AdornerDecorator

直接修改ItemsControl的ItemTemplate,将每个项的根元素设为AdornerDecorator,内部放置原控件。这样所有绑定的子控件都会拥有独立的AdornerLayer,避免共享层的位置计算错误。

示例XAML:

<ItemsControl ItemsSource="{Binding YourItemCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <!-- 统一包裹AdornerDecorator -->
            <AdornerDecorator>
                <!-- 原控件,比如TextBox、ComboBox等 -->
                <TextBox Text="{Binding Property, ValidatesOnNotifyDataErrors=True}" />
            </AdornerDecorator>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

如果ItemTemplate包含多种控件类型,可用ContentControl动态加载内容,保持AdornerDecorator的统一包裹:

<ItemsControl ItemsSource="{Binding YourItemCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <AdornerDecorator>
                <ContentControl Content="{Binding}" />
            </AdornerDecorator>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

2. 自定义ItemsControl自动添加AdornerDecorator

如果项目中有多个ItemsControl需要修复,自定义一个继承自ItemsControl的控件,在PrepareContainerForItemOverride方法中自动给每个容器添加AdornerDecorator,一次修改全局生效。

C#代码:

using System.Windows;
using System.Windows.Controls;

public class ValidationFixedItemsControl : ItemsControl
{
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        base.PrepareContainerForItemOverride(element, item);

        if (element is ContentPresenter presenter)
        {
            var decorator = new AdornerDecorator();
            // 将原内容转移到AdornerDecorator内部
            if (presenter.Content is UIElement contentElement)
            {
                decorator.Child = contentElement;
                presenter.Content = decorator;
            }
        }
    }
}

使用时直接替换原ItemsControl:

<local:ValidationFixedItemsControl ItemsSource="{Binding YourItemCollection}">
    <ItemsControl.ItemTemplate>
        <!-- 原模板内容无需修改 -->
        <DataTemplate>
            <TextBox Text="{Binding Property, ValidatesOnNotifyDataErrors=True}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</local:ValidationFixedItemsControl>

额外说明

  • 该bug在.NET Core 3.1及以后的.NET版本中已被修复,若后续有框架升级计划,可直接迁移解决。
  • 第一种方案适合单个ItemsControl的快速修复,第二种适合多场景的全局统一处理。

内容的提问来源于stack exchange,提问作者Jeremy Deters

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 17:03:14