2008-11-26 5 views
21

Ich habe eine Situation, wo ich wpf Datenbindung und Validierung mit der ExceptionValidationRule verwenden.Wie entferne ich das rote Rechteck, wenn meine Validierung der wpf-Bindung fehlgeschlagen ist und das enthaltene Panel nicht mehr sichtbar ist?

Ein anderer Teil der Lösung invovles kollabiert einige Panels und zeigt andere.

Wenn eine Validierungsausnahme gesetzt ist - d. H. Die UI zeigt einen roten Rahmen um das UI-Element mit dem Validierungsproblem und das enthaltene Panel ist ausgeblendet, wird der rote Rahmen immer noch angezeigt. Das soll eindeutig nicht sein? Gibt es einen Workaround dafür? Wer weiß, ob dies beabsichtigt ist?

Minimales Codebeispiel bereitgestellt (nicht mein tatsächlicher Code, aber repliziert das Problem). Erstellen Sie eine neue WpfApplication (ich nannte mein WpfDataBindingProblem).

XAML für window1 ist wie folgt:

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

Der Code für window1 wie folgt:

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

} 

das Problem zu reproduzieren, die Anwendung auszuführen. Löschen Sie den Standard Text aus dem Textfeld und Registerkarte aus - rotes Rechteck wird angezeigt, ein Validierungsproblem anzuzeigen. Drück den Knopf. Das Panel, das das Steuerelement mit dem roten Rechteck enthält, ist ausgeblendet und ein anderes Panel wird angezeigt, aber das rote Rechteck bleibt erhalten. Aargh!

Alle Hilfe sehr geschätzt.

PS Entschuldigung für lange Frage Titel!

Antwort

22

Wenn ich mich richtig erinnere, dann ist dies ein bekanntes Problem. Wir re-Templat Textbox gehören die folgenden:

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

Donnelle, Das ist fantastisch! Genau das, was ich brauche. Vielen Dank, Sam –

+0

Gern geschehen. Froh, dass ich Helfen kann! – Donnelle

+0

Das ist erstaunlich einfach. Vielen Dank!!! – Pwninstein

1

Ich habe eine Antwort auf das Problem selbst, das ist mein Button Click Event zu ändern, das die Sichtbarkeit der Panels ändert. Dies würde so etwas ändern:

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

Die Update() und Update() die Wirkung haben, die erneute Anwenden und das rote Rechteck zu entfernen, aber dies scheint wie eine hässliche Hack. Sicherlich sollte das wpf-Framework das rote Rechteck für mich verstecken, wenn das enthaltende Panel zusammengebrochen ist. Jede sauberere Korrektur, bei der ich nicht mit dem verbindlichen Ausdruck herumhantieren muss, erhält meine Stimme.

Danke,

Sam