Подтвердить что ты не робот

Как мне избавиться от красного прямоугольника, когда моя проверка привязки wpf не удалась, а содержащая панель больше не видна?

У меня есть ситуация, когда я использую привязку и проверку данных wpf с помощью ExceptionValidationRule.

Другая часть решения invovles сворачивает некоторые панели и показывает другие.

Если исключение проверки установлено, то есть пользовательский интерфейс показывает красную рамку вокруг элемента пользовательского интерфейса с проблемой проверки, а содержащая панель сбрасывается, красная рамка все еще отображается. Это, очевидно, не должно быть? Есть ли обходной путь для этого? Кто-нибудь знает, если это по дизайну?

Приведен пример минимального кода (не мой фактический код, но реплицирует проблему). Создайте новую WpfApplication (я назвал мою WpfDataBindingProblem).

xaml для окна1 выглядит следующим образом:

<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>

Код для окна1 выглядит следующим образом:

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);
            }
        }
    }

}

Чтобы воспроизвести проблему, запустите приложение. Удалите текст по умолчанию из текстового поля, а вкладка - красный прямоугольник, показывающий проблему проверки. Нажмите кнопку. Панель, содержащая элемент управления с красным прямоугольником, скрыта, и отображается другая панель, но красный прямоугольник остается. Aargh!

Вся помощь очень ценится.

PS извинения за длинный вопрос!

4b9b3361

Ответ 1

Если я правильно помню, это известная проблема. Мы переформатировали текстовое поле, чтобы включить следующее:

<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>

Ответ 2

У меня есть ответ на проблему, которая заключается в изменении события нажатия кнопки, которое изменяет видимость панелей. Это изменилось бы на что-то вроде этого:

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;
    }
}

UpdateSource() и UpdateTarget() имеют эффект повторного применения и удаления красного прямоугольника, но это кажется уродливым взломом. Разумеется, структура wpf должна скрывать красный прямоугольник для меня, когда панель сложения рушится. Любое исправление, которое не требует, чтобы я возился с обязательным выражением, получает мой голос.

Спасибо,

Сэм