当 HasError 为 false 时验证错误装饰不会清除

发布于 2025-01-07 22:56:06 字数 9481 浏览 5 评论 0原文

简介

我创建了一个DecimalTextBox用户控件,它附加了ValidationRule以防止空值,有最小和最大范围,并且有事件处理程序以防止非十进制值。我已经在绑定上使用了,

ValidatesOnTargetUpdated="True"

因为我希望立即激活验证(并且之前我遇到了一个问题,即最小值和最大值发生了变化,但验证没有被重新评估)。

我所做的 null 验证取决于“AllowNull”依赖属性的值:如果控件指定 true,则即使该值为 null,该控件也有效。如果为 false,则不允许为 null。此属性的默认值为 False


问题

在某个 UserControl 中使用它时,我将 AllowNull 设置为 true。不幸的是,由于 ValidatesOnTargetUpdated 设置为 true,因此在 xaml 将 AllowNull 设置为 true 之前控件已验证,而它仍处于默认状态false 设置。

这会导致加载前出错,因为与 TextBox 文本的绑定还没有解析,因此加载前不允许为 null,并且文本值为 null。

这一切都很好,因为加载后,将使用新的 AllowNull 值(true)重新评估验证,并且错误将被删除。

但是红色验证装饰仍然存在。不完全确定如何摆脱它。


守则 文本框用户控件的 xaml:

<UserControl x:Class="WPFTest.DecimalTextBox"
         x:Name="DecimalBox"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:v="clr-namespace:ValidationRules"
         mc:Ignorable="d" 
         d:DesignHeight="25" d:DesignWidth="100" Initialized="DecimalBox_Initialized" >

    <TextBox x:Name="textbox">
        <TextBox.Text>
            <Binding ElementName="DecimalBox" TargetNullValue="" Path="Text" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" ValidatesOnDataErrors="True" ValidatesOnExceptions="True" NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <v:DecimalRangeRule  ValidatesOnTargetUpdated="True">
                        <v:DecimalRangeRule.MinMaxRange>
                            <v:MinMaxValidationBindings x:Name="minMaxValidationBindings"/>
                        </v:DecimalRangeRule.MinMaxRange> 
                    </v:DecimalRangeRule>
                    <v:NotEmptyRule  ValidatesOnTargetUpdated="True">
                        <v:NotEmptyRule.AllowNull>
                            <v:AllowNullValidationBinding x:Name="allowNullValidationBindings"></v:AllowNullValidationBinding>
                        </v:NotEmptyRule.AllowNull>
                    </v:NotEmptyRule>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
</UserControl>

控件背后的代码:

    public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(textboxcontrol), new PropertyMetadata());
    public static DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(decimal), typeof(DecimalTextBox), new PropertyMetadata(0M));
    public static DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(decimal), typeof(DecimalTextBox), new PropertyMetadata(0M));
    public static DependencyProperty AllowNullProperty = DependencyProperty.Register("AllowNull", typeof(bool), typeof(DecimalTextBox), new UIPropertyMetadata(false));

    public bool AllowNull
    {
        get { return (bool)GetValue(AllowNullProperty); }
        set { SetValue(AllowNullProperty, value); }
    }
    public decimal Minimum
    {
        get { return (decimal)GetValue(MinimumProperty); }
        set { SetValue(MinimumProperty, value); }
    }
    public decimal Maximum
    {
        get { return (decimal)GetValue(MaximumProperty); }
        set { SetValue(MaximumProperty, value); }
    }
    public string Text
    {
        get
        {
            return (string)GetValue(TextProperty);
        }
        set
        {
            SetValue(TextProperty, value);
        }
    }



    private void DecimalBox_Initialized(object sender, EventArgs e)
    {
        Binding minBinding = new Binding("Minimum");
        minBinding.Source = this;
        Binding maxBinding = new Binding("Maximum");
        maxBinding.Source = this;
        Binding allownullBinding = new Binding("AllowNull");
        allownullBinding.Source = this;

        minMaxValidationBindings.SetBinding(ValidationRules.MinMaxValidationBindings.minProperty, minBinding);
        BindingOperations.SetBinding(minMaxValidationBindings, ValidationRules.MinMaxValidationBindings.maxProperty, maxBinding);
        BindingOperations.SetBinding(allowNullValidationBindings, ValidationRules.AllowNullValidationBinding.allowNullProperty, allownullBinding);
    }

以及验证规则(#Note:它们位于 ValidationRules 命名空间内):

public class NotEmptyRule : ValidationRule
{

    public NotEmptyRule()
    {
    }
    private AllowNullValidationBinding _allowNullBinding;

    public AllowNullValidationBinding AllowNull
    {
        get { return _allowNullBinding; }
        set { _allowNullBinding = value; }
    }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        if (!_allowNullBinding.AllowNull)
            if (string.IsNullOrEmpty((string)value))
                return new ValidationResult(false,
                  "Value cannot be null or empty.");
            else
                return new ValidationResult(true, null);

        else
           return new ValidationResult(true, null);

    }
}

public class DecimalRangeRule : ValidationRule
{
    private MinMaxValidationBindings _bindableMinMax;
    public MinMaxValidationBindings MinMaxRange
    {
        get { return _bindableMinMax; }
        set
        {
            _bindableMinMax = value;

        }
    }


    public DecimalRangeRule()
    {

    }
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {

        decimal number = 0;

        if(decimal.TryParse((string)value,out number))
            if (_bindableMinMax.Min != _bindableMinMax.Max || _bindableMinMax.Min != 0)
            {
                if ((number < _bindableMinMax.Min) || (number > _bindableMinMax.Max))
                {
                    return new ValidationResult(false,
                      "Please enter an decimal in the range: " + _bindableMinMax.Min + " - " + _bindableMinMax.Max + ".");
                }
                else
                {
                    return new ValidationResult(true, null);
                }
            }
            else
                return new ValidationResult(true, null);
        else
            return new ValidationResult(true, null);
    }
}

public class AllowNullValidationBinding:FrameworkElement
{
     public static readonly DependencyProperty allowNullProperty = DependencyProperty.Register(
        "AllowNull", typeof(bool), typeof(AllowNullValidationBinding), new UIPropertyMetadata(false));

    public bool AllowNull
    {
        get{return (bool)GetValue(allowNullProperty);}
        set{SetValue(allowNullProperty,value);}
    }
    public AllowNullValidationBinding()
    {}
}

public class MinMaxValidationBindings : FrameworkElement
{
    public static readonly DependencyProperty minProperty = DependencyProperty.Register(
        "Min", typeof(decimal), typeof(MinMaxValidationBindings), new UIPropertyMetadata(0.0m));

    public static readonly DependencyProperty maxProperty = DependencyProperty.Register(
        "Max", typeof(decimal), typeof(MinMaxValidationBindings), new UIPropertyMetadata(0.0m));

    public decimal Min
    {
        get { return (decimal)GetValue(minProperty); }
        set { SetValue(minProperty, value); }
    }

    public decimal Max
    {
        get { return (decimal)GetValue(maxProperty); }
        set { SetValue(maxProperty, value); }
    }

    public MinMaxValidationBindings() { }

}

使用 FrameworkElement 绑定,以便我的 ValidationRules 可以具有要绑定的依赖属性。这允许我在控件之外指定最小值和最大值。


摘要

我已经使用Validation.GetHasError(DecimalBox)检查了HasError(对于两者控件本身以及它的内部 TextBox) 加载后会产生 false。

我知道如果删除 ValidatesOnTargetUpdated="True" 红色就不会出现,但我需要它。那么为什么验证被重新评估但红色边框装饰却没有消失呢?

我对 Validation 类或其静态方法了解不多,但是其中是否有一些东西可以删除装饰。 ClearInvalid 方法不会有帮助,因为我没有提供它的错误。

有什么想法吗?

u_u


编辑

我做了更多调查并发现了以下内容:

  1. 如果我将加载后的文本更改为大于最大值的数量,然后将其改回错误装饰器消失
  2. 如果我以编程方式将控件加载事件内的 Text 依赖属性的值更改为大于最大值的值,然后将其改回来,装饰器仍然存在
  3. 如果我在加载后将文本更改为空值,然后将其更改回装饰器仍然存在
  4. 如果我更改绑定到视图模型构造函数内文本的视图模型属性值,装饰器仍然存在
  5. 如果我更改绑定到构造函数内文本的视图模型属性值将视图模型设置为大于最大值的值,然后将其更改回来,装饰器仍然存在
  6. 如果我将绑定到带有按钮的文本的视图模型属性的值更改为不同的值,然后将其更改回来,装饰器消失
  7. 如果我更改绑定到文本的视图模型属性的值将按钮设置为值大于最大值,然后将其改回来,装饰器消失

我仍然相当困惑。我尝试过像 UpdateLayout() 这样的方法,并尝试将装饰器移动到不同的控件,然后使用 Validation.SetValidationAdornerSite 将其移回。我继续努力,但我不知道该怎么做。

u_u


第二次编辑

好吧,我同时所做的是在 TextBox 周围放置一个 AdornerDecorator,然后在文本框加载事件中将最大值更改为 1,将值更改为 2,然后将其更改回来,以便使文本框刷新。

这是可行的,但我讨厌这个想法,因为它的代码很糟糕。

然而,这个解决方案不再可行。我有一些代码正在对绑定到这些 DecimalTextBox 之一的属性之一的属性进行更改。然后,由于属性在加载事件中被更改和更改回来,其他代码也正在运行并导致错误。我必须找到比这更好的解决方案。

有谁知道如何刷新验证装饰器?

u_u

INTRODUCTION

I have created a DecimalTextBox user control which has ValidationRules attached to it to prevent nulls, have a minimum and maximum range and it has event handlers to prevent non-decimal values. I have used

ValidatesOnTargetUpdated="True"

on the bindings because I want the validation to be activated immediately (and I had an issue before where the min and max values were changing but the validation wasn't being reevaluated).

The null validation I have done is dependent on the value of an "AllowNull" dependency property: If the control specifies true then the control is valid even when the value is null. When false then null is not allowed. The default of this property is False


THE PROBLEM

I am setting the AllowNull to true when using it in a certain UserControl. Unfortunately because the ValidatesOnTargetUpdated is set to true, the control is validated before the xaml sets the AllowNull to true, while it is still in its default false setting.

This causes an error before loading, as the binding to the text of the TextBox is also not resolved yet, so before loading it doesn't allow null, and the value of the text is null.

This is all fine and dandy because after the loading the validation is reevaluated with the new AllowNull value (of true) and the error is removed.

However the red validation adornment remains. Not entirely sure how to get rid of it.


THE CODE
The xaml for the textbox usercontrol:

<UserControl x:Class="WPFTest.DecimalTextBox"
         x:Name="DecimalBox"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:v="clr-namespace:ValidationRules"
         mc:Ignorable="d" 
         d:DesignHeight="25" d:DesignWidth="100" Initialized="DecimalBox_Initialized" >

    <TextBox x:Name="textbox">
        <TextBox.Text>
            <Binding ElementName="DecimalBox" TargetNullValue="" Path="Text" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" ValidatesOnDataErrors="True" ValidatesOnExceptions="True" NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <v:DecimalRangeRule  ValidatesOnTargetUpdated="True">
                        <v:DecimalRangeRule.MinMaxRange>
                            <v:MinMaxValidationBindings x:Name="minMaxValidationBindings"/>
                        </v:DecimalRangeRule.MinMaxRange> 
                    </v:DecimalRangeRule>
                    <v:NotEmptyRule  ValidatesOnTargetUpdated="True">
                        <v:NotEmptyRule.AllowNull>
                            <v:AllowNullValidationBinding x:Name="allowNullValidationBindings"></v:AllowNullValidationBinding>
                        </v:NotEmptyRule.AllowNull>
                    </v:NotEmptyRule>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
</UserControl>

The code behind for the control:

    public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(textboxcontrol), new PropertyMetadata());
    public static DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(decimal), typeof(DecimalTextBox), new PropertyMetadata(0M));
    public static DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(decimal), typeof(DecimalTextBox), new PropertyMetadata(0M));
    public static DependencyProperty AllowNullProperty = DependencyProperty.Register("AllowNull", typeof(bool), typeof(DecimalTextBox), new UIPropertyMetadata(false));

    public bool AllowNull
    {
        get { return (bool)GetValue(AllowNullProperty); }
        set { SetValue(AllowNullProperty, value); }
    }
    public decimal Minimum
    {
        get { return (decimal)GetValue(MinimumProperty); }
        set { SetValue(MinimumProperty, value); }
    }
    public decimal Maximum
    {
        get { return (decimal)GetValue(MaximumProperty); }
        set { SetValue(MaximumProperty, value); }
    }
    public string Text
    {
        get
        {
            return (string)GetValue(TextProperty);
        }
        set
        {
            SetValue(TextProperty, value);
        }
    }



    private void DecimalBox_Initialized(object sender, EventArgs e)
    {
        Binding minBinding = new Binding("Minimum");
        minBinding.Source = this;
        Binding maxBinding = new Binding("Maximum");
        maxBinding.Source = this;
        Binding allownullBinding = new Binding("AllowNull");
        allownullBinding.Source = this;

        minMaxValidationBindings.SetBinding(ValidationRules.MinMaxValidationBindings.minProperty, minBinding);
        BindingOperations.SetBinding(minMaxValidationBindings, ValidationRules.MinMaxValidationBindings.maxProperty, maxBinding);
        BindingOperations.SetBinding(allowNullValidationBindings, ValidationRules.AllowNullValidationBinding.allowNullProperty, allownullBinding);
    }

And the Validation Rules (#Note: They are inside the ValidationRules namespace):

public class NotEmptyRule : ValidationRule
{

    public NotEmptyRule()
    {
    }
    private AllowNullValidationBinding _allowNullBinding;

    public AllowNullValidationBinding AllowNull
    {
        get { return _allowNullBinding; }
        set { _allowNullBinding = value; }
    }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        if (!_allowNullBinding.AllowNull)
            if (string.IsNullOrEmpty((string)value))
                return new ValidationResult(false,
                  "Value cannot be null or empty.");
            else
                return new ValidationResult(true, null);

        else
           return new ValidationResult(true, null);

    }
}

public class DecimalRangeRule : ValidationRule
{
    private MinMaxValidationBindings _bindableMinMax;
    public MinMaxValidationBindings MinMaxRange
    {
        get { return _bindableMinMax; }
        set
        {
            _bindableMinMax = value;

        }
    }


    public DecimalRangeRule()
    {

    }
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {

        decimal number = 0;

        if(decimal.TryParse((string)value,out number))
            if (_bindableMinMax.Min != _bindableMinMax.Max || _bindableMinMax.Min != 0)
            {
                if ((number < _bindableMinMax.Min) || (number > _bindableMinMax.Max))
                {
                    return new ValidationResult(false,
                      "Please enter an decimal in the range: " + _bindableMinMax.Min + " - " + _bindableMinMax.Max + ".");
                }
                else
                {
                    return new ValidationResult(true, null);
                }
            }
            else
                return new ValidationResult(true, null);
        else
            return new ValidationResult(true, null);
    }
}

public class AllowNullValidationBinding:FrameworkElement
{
     public static readonly DependencyProperty allowNullProperty = DependencyProperty.Register(
        "AllowNull", typeof(bool), typeof(AllowNullValidationBinding), new UIPropertyMetadata(false));

    public bool AllowNull
    {
        get{return (bool)GetValue(allowNullProperty);}
        set{SetValue(allowNullProperty,value);}
    }
    public AllowNullValidationBinding()
    {}
}

public class MinMaxValidationBindings : FrameworkElement
{
    public static readonly DependencyProperty minProperty = DependencyProperty.Register(
        "Min", typeof(decimal), typeof(MinMaxValidationBindings), new UIPropertyMetadata(0.0m));

    public static readonly DependencyProperty maxProperty = DependencyProperty.Register(
        "Max", typeof(decimal), typeof(MinMaxValidationBindings), new UIPropertyMetadata(0.0m));

    public decimal Min
    {
        get { return (decimal)GetValue(minProperty); }
        set { SetValue(minProperty, value); }
    }

    public decimal Max
    {
        get { return (decimal)GetValue(maxProperty); }
        set { SetValue(maxProperty, value); }
    }

    public MinMaxValidationBindings() { }

}

The FrameworkElement bindings are used so my ValidationRules can have dependency properties to bind to. This allows me to specify a min and max value outside the control.


SUMMARY

I've checked the HasError by using the Validation.GetHasError(DecimalBox) (for both the control itself as well as it's inner TextBox) after load and it produces false.

I know that if I remove the ValidatesOnTargetUpdated="True" The red wont appear, but I need it. So why is the validation being reevaluated but the red border adornment not dissapearing?

I don't know much about the Validation class or its static methods, but is there something in there to remove the adornment. The ClearInvalid method isn't gonna help cause I don't have an error to supply it.

Any ideas?

u_u


EDIT

I've done some more investigating and found the following things:

  1. If I change the text after the load to to an amount greater then the maximum and then change it back the error adorner dissapears
  2. If I change the value of the Text dependency property inside the controls load event programically to an amount greater then the maximum and change it back, the adorner is still there.
  3. If I change the text after the load to a null value and then change it back the adorner is still there.
  4. If I change the value of the viewmodel's property bound to the text inside the constructor of the view model, the adorner is still there
  5. If I change the value of the viewmodel's property bound to the text inside the constructor of the view model to a value greater than the maximum, and then change it back, the adorner is still there.
  6. If I change the value of the viewmodel's property bound to the text with a button to a different value, and then change it back, the adorner dissapears
  7. If I change the value of the viewmodel's property bound to the text with a button to a value greater than the maximum, and then change it back, the adorner dissapears

I'm still fairly stumped. Ive tried methods like UpdateLayout() and tried moving the adorner to different controls and moving it back using the Validation.SetValidationAdornerSite. Ima keep trying but I dont know what to do really.

u_u


2ND EDIT

Ok what I had done in the meantime was place an AdornerDecorator around the TextBox and then in the textboxes load event change the maximum to 1 and the value to 2, then change it back in order to get the textbox to refresh.

This was working, but I hated the idea cause its horrible code.

However this solution is no longer viable. I had some code that was doing stuff on the property changed of one of the properties bound to one of these DecimalTextBoxes. Then because the property was being changed and changed back in the load event, the other code was also being run and causing errors. I have to find a better solution then this.

Does anyone know how to refresh the validation adorner?

u_u

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

败给现实 2025-01-14 22:56:06

这里有一些针对该问题的解决方法,因为我遇到过这个问题,但无法找到任何内容,我怀疑这是框架中某个地方由竞争条件引起的错误,但找不到任何支持的内容。

对私有字段的反射(恶心)

因为您知道您的字段没有错误,所以您可以这样做来迭代控件并杀死装饰器

var depPropGetter = typeof (Validation).GetField("ValidationAdornerProperty", BindingFlags.Static | BindingFlags.NonPublic);
var validationAdornerProperty = (DependencyProperty)depPropGetter.GetValue(null);
var adorner = (Adorner)DateActionDone.GetValue(validationAdornerProperty);

if (adorner != null && Validation.GetHasError(MyControl))
{
    var adorners = AdornerLayer.GetAdornerLayer(MyControl).GetAdorners(MyControl);
    if (adorners.Contains(adorner))
        AdornerLayer.GetAdornerLayer(MyControl).Remove(adorner);
}

或者您可以通过反射调用 Validation.ShowAdornerHelper 方法,该方法我没有直接尝试过,所以没有费心编写代码。

强制刷新所有绑定

我们可以利用您的发现,使绑定无效然后再次有效将为我们清除装饰器。

这是我决定采用的解决方案,并且恰好非常有效。

因为我在基本视图模型中使用 IDataErrorInfo,所以我可以按照此方法做一些事情,具体取决于您处理验证的方式,您可能会在重新验证这些内容时遇到更多麻烦。

    string IDataErrorInfo.this[string columnName]
    {
        get
        {
            if (_refreshing) return "Refreshing";
            return ValidationEngine.For(this.GetType()).GetError(this, columnName);
        }
    }

    bool _refreshing = false;
    public void RefreshValidation()
    {
        _refreshing = true;
        this.NotifyOfPropertyChange(string.Empty);
        _refreshing = false;
        this.NotifyOfPropertyChange(string.Empty);
    }

Here are a couple of workarounds for the problem as I've encountered it and been unable to find anything on it, I suspect that it's a bug somewhere in the framework caused by a race condition but couldn't find anything to back that up.

Reflection on private fields (yuck)

Because you know that your field doesn't have errors you can do this to iterate the controls and kill the adorners

var depPropGetter = typeof (Validation).GetField("ValidationAdornerProperty", BindingFlags.Static | BindingFlags.NonPublic);
var validationAdornerProperty = (DependencyProperty)depPropGetter.GetValue(null);
var adorner = (Adorner)DateActionDone.GetValue(validationAdornerProperty);

if (adorner != null && Validation.GetHasError(MyControl))
{
    var adorners = AdornerLayer.GetAdornerLayer(MyControl).GetAdorners(MyControl);
    if (adorners.Contains(adorner))
        AdornerLayer.GetAdornerLayer(MyControl).Remove(adorner);
}

Alternatively you can call the Validation.ShowAdornerHelper method through reflection, which I hadn't directly tried so haven't bothered writing code for.

Refreshing ALL bindings forcefully

We can take advantage of your finding that making the binding invalid and then valid again will clear the adorner down for us.

This is the solution i've decided to go with, and happens to be quite effective.

Because I'm using IDataErrorInfo in my base view model I can do something along the lines of this, depending on how you handle your validation you might have more trouble getting these to revalidate.

    string IDataErrorInfo.this[string columnName]
    {
        get
        {
            if (_refreshing) return "Refreshing";
            return ValidationEngine.For(this.GetType()).GetError(this, columnName);
        }
    }

    bool _refreshing = false;
    public void RefreshValidation()
    {
        _refreshing = true;
        this.NotifyOfPropertyChange(string.Empty);
        _refreshing = false;
        this.NotifyOfPropertyChange(string.Empty);
    }
故事和酒 2025-01-14 22:56:06

尝试删除控件的事件 LayoutUpdated 上的错误(在事件上放置一个标志以仅执行一次)

Validation.ClearInvalid(SystemCode.GetBindingExpression(TextBox.TextProperty));

,然后重新评估您的验证规则(刷新您的绑定)。

var dp = SystemCode.GetBindingExpression(TextBox.TextProperty);
dp.UpdateSource();

Try with to remove the error on event LayoutUpdated of your control (put a flag on the event to do it only once)

Validation.ClearInvalid(SystemCode.GetBindingExpression(TextBox.TextProperty));

and then re-evaluate your Validations Rules (refreshing your bindings).

var dp = SystemCode.GetBindingExpression(TextBox.TextProperty);
dp.UpdateSource();
洒一地阳光 2025-01-14 22:56:06

我遇到了与此类似的问题,即使潜在的错误消失,装饰器也不会消失。

我发现的最终解决方法是通过调用强制更新布局,

Control.UpdateLayout()

以某种方式强制 WPF 同步备份。我对 Control_Loaded 事件处理程序进行了更新,但它也可能在其他时候解决该问题。

I had an issue similar to this where the adorner was not going away even though the underlying error did.

The ultimate workaround that I discovered was to force the layout to be updated by calling

Control.UpdateLayout()

which somehow forced WPF to sync-back up. I did the Update on a Control_Loaded event handler, but it might fix the issue at other times as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文