2008-11-26 7 views
21

J'ai une situation où j'utilise la liaison de données wpf et la validation en utilisant le ExceptionValidationRule.Comment se débarrasser du rectangle rouge lorsque ma validation de liaison wpf a échoué et que le panneau contenant n'est plus visible?

Une autre partie de la solution prévoit l'effondrement de certains panneaux et l'affichage d'autres.

Si une exception de validation est définie, à savoir que l'interface utilisateur affiche une bordure rouge autour de l'élément d'interface utilisateur avec le problème de validation et que le panneau conteneur est réduit, la bordure rouge s'affiche toujours. Ce n'est clairement pas destiné à être? Y at-il une solution de contournement pour cela? Quelqu'un sait-il si c'est par conception?

Exemple de code minimal fourni (pas mon code réel, mais réplique le problème). Créer un nouveau WpfApplication (j'ai appelé le mien WpfDataBindingProblem).

Le XAML pour fenêtre1 est la suivante:

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

Le code pour fenêtre1 est la suivante:

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

} 

Pour reproduire le problème, exécutez l'application. Supprimer le par défaut texte de la zone de texte et tabulation - rectangle rouge est indiqué indiquant un problème de validation. Cliquez sur le bouton. Le panneau contenant un contrôle avec un rectangle rouge est masqué et un autre panneau est affiché, mais le rectangle rouge reste. Aargh!

Toute aide très appréciée.

PS excuses pour le long titre de la question!

Répondre

22

Si je me souviens bien, cela est un problème connu. Nous textbox ré-basé sur un modèle pour inclure les éléments suivants:

<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, C'est fantastique! Exactement ce dont j'ai besoin. Un grand merci, Sam –

+0

De rien. Heureux de vous aider! – Donnelle

+0

C'est incroyablement simple. Merci!!! – Pwninstein

1

J'ai moi-même une réponse au problème qui est de changer mon événement de clic de bouton qui change la visibilité des panneaux. Cela changerait quelque chose comme ceci:

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

Le UpdateSource() et UpdateTarget() ont pour effet de réappliquer et le retrait du rectangle rouge, mais cela semble être une bidouille horrible. Sûrement le cadre wpf devrait cacher le rectangle rouge lorsque le panneau contenant est réduit. Toute solution nettoyante qui ne nécessite pas que je joue avec l'expression de liaison obtient mon vote.

Merci,

Sam