C# 当我的 wpf 绑定验证失败并且包含面板不再可见时,如何摆脱红色矩形?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/321327/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:08:49  来源:igfitidea点击:

How do I get rid of the red rectangle when my wpf binding validation has failed and the containing panel is no longer visible?

c#.netwpfvalidationdata-binding

提问by Sam Meldrum

I have a situation where I am using wpf data binding and validation using the ExceptionValidationRule.

我有一种情况,我使用 ExceptionValidationRule 使用 wpf 数据绑定和验证。

Another part of the solution invovles collapsing some panels and showing others.

解决方案的另一部分涉及折叠一些面板并显示其他面板。

If a validation exception is set - i.e. the UI is showing a red border around the UI element with the validation problem, and the containing panel is collapsed, the red border is still displayed. This is clearly not meant to be? Is there a workaround for this? Anyone know if this is by design?

如果设置了验证异常 - 即 UI 在存在验证问题的 UI 元素周围显示红色边框,并且包含面板已折叠,则仍会显示红色边框。这显然不是故意的?有解决方法吗?有谁知道这是否是设计使然?

Minimal code example provided (not my actual code, but replicates the problem). Create a new WpfApplication (I called mine WpfDataBindingProblem).

提供了最少的代码示例(不是我的实际代码,而是复制了问题)。创建一个新的 WpfApplication(我称之为 WpfDataBindingProblem)。

The xaml for window1 is as follows:

window1 的 xaml 如下:

<Window x:Class="WpfDataBindingProblem.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel Margin="5">

        <StackPanel Name="panel1" Visibility="Visible" Margin="5">
            <TextBox Name="DataBoundTextBox">
                <Binding Path="TextValue">
                    <Binding.ValidationRules>
                        <ExceptionValidationRule/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox>
        </StackPanel>

        <StackPanel Name="panel2" Visibility="Collapsed" Margin="5">
            <TextBlock>
                The quick brown fox jumps over the lazy dog.
            </TextBlock>
        </StackPanel>

        <Button Click="Button_Click" Margin="5">
            Toggle panels
        </Button>

    </StackPanel>
</Window>

The code for window1 is as follows:

window1的代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfDataBindingProblem {

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

            this.DataContext = new MyClass("default");
        }

        private void Button_Click(object sender, RoutedEventArgs e) {
            panel1.Visibility = panel1.Visibility == Visibility.Collapsed ?
                Visibility.Visible : Visibility.Collapsed;
            panel2.Visibility = panel2.Visibility == Visibility.Collapsed ?
                Visibility.Visible : Visibility.Collapsed;
        }
    }

    public class MyClass : INotifyPropertyChanged {

        private string mTextValue;

        public MyClass(string defaultText) {
            TextValue = defaultText;
        }

        public string TextValue {
            get {
                return mTextValue;
            }
            set {
                mTextValue = value;
                if (string.IsNullOrEmpty(mTextValue)) {
                    throw new ApplicationException("Text value cannot be empty");
                }
                OnPropertyChanged(new PropertyChangedEventArgs("TextValue"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) {
            if (this.PropertyChanged != null) {
                this.PropertyChanged(this, e);
            }
        }
    }

}

To reproduce the problem, run the application. Delete the defaulttext from the textbox and tab off - red rectangle is shown indicating a validation problem. Click the button. Panel containing control with red rectangle is hidden and another panel is shown, but the red rectangle remains. Aargh!

要重现该问题,请运行该应用程序。从文本框中删除默认文本并关闭标签 - 显示红色矩形表示验证问题。单击按钮。包含红色矩形控件的面板被隐藏并显示另一个面板,但红色矩形仍然存在。啊!

All help much appreciated.

非常感谢所有帮助。

PS apologies for long question title!

PS 为长问题道歉!

采纳答案by Donnelle

If I remember correctly, this is a known issue. We re-templated textbox to include the following:

如果我没记错的话,这是一个已知问题。我们重新设计了文本框以包含以下内容:

<Setter Property="Validation.ErrorTemplate">
    <Setter.Value>
        <ControlTemplate>
            <ControlTemplate.Resources>
                <BooleanToVisibilityConverter x:Key="converter" />
        </ControlTemplate.Resources>
            <DockPanel LastChildFill="True">
                <Border 
                    BorderThickness="1"
                    BorderBrush="Red"
                    Visibility="{Binding ElementName=placeholder, Mode=OneWay, Path=AdornedElement.IsVisible, Converter={StaticResource converter}}">
                    <AdornedElementPlaceholder x:Name="placeholder" />
                </Border>
             </DockPanel>
         </ControlTemplate>
    </Setter.Value>
</Setter>

回答by Sam Meldrum

I have an answer to the problem myself which is to change my button click event which changes the visibility of the panels. This would change to something like this:

我自己对这个问题有一个答案,那就是改变我的按钮点击事件,这会改变面板的可见性。这会变成这样的:

private void Button_Click(object sender, RoutedEventArgs e) {
    if (panel1.Visibility == Visibility.Collapsed) {
        panel1.Visibility = Visibility.Visible;
        DataBoundTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
        panel2.Visibility = Visibility.Collapsed;
    }
    else {
        panel1.Visibility = Visibility.Collapsed;
        DataBoundTextBox.GetBindingExpression(TextBox.TextProperty).UpdateTarget();
        panel2.Visibility = Visibility.Visible;
    }
}

The UpdateSource()and UpdateTarget()have the effect of reapplying and removing the red rectangle, but this seems like an ugly hack. Surely the wpf framework should be hiding the red rectangle for me when the containing panel is collapsed. Any cleaner fix that doesn't require me to fiddle with the binding expression gets my vote.

UpdateSource()UpdateTarget()必须重新申请并去除红色矩形的效果,但是这似乎是一个丑陋的黑客。当然,当包含面板折叠时,wpf 框架应该为我隐藏红色矩形。任何不需要我摆弄绑定表达式的更干净的修复都会得到我的投票。

Thanks,

谢谢,

Sam

山姆