2012-09-19 7 views
8

Il semble que j'ai lu une autre question/réponse sur ce site à propos de ce problème, mais je ne me souviens pas de la réponse et maintenant je ne trouve pas le message original. Je ne suis pas un fan du modèle d'erreur par défaut dans WPF. Je comprends comment changer ce modèle d'erreur. Cependant, si j'ajoute du contenu à la fin, disons, d'une zone de texte, la taille de la zone de texte ne change pas et le contenu ajouté sera (potentiellement) tronqué. Comment puis-je modifier la zone de texte (je crois que la terminologie correcte est l'élément orné) dans ce scénario afin que rien ne soit coupé?Erreur Modèle de conception

Voici le XAML pour le modèle d'erreur:

<Style TargetType="{x:Type TextBox}"> 
    <Setter Property="Validation.ErrorTemplate"> 
    <Setter.Value> 
     <ControlTemplate> 
     <StackPanel> 
      <AdornedElementPlaceholder /> 
      <TextBlock Foreground="Red" Text="Error..." /> 
     </StackPanel> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 

Voici le XAML pour deux zones de texte sous la forme:

<StackPanel> 
    <TextBox Text="{Binding...}" /> 
    <TextBox /> 
</StackPanel> 
+2

S'il vous plaît ajouter le XAM concerné L code à vous question – Spontifixus

+0

J'ai ajouté le XAML qui pourrait être utilisé. Le XAML est beaucoup plus simple que ce que j'utiliserais mais il démontre correctement le problème. Tout message d'erreur serait réellement affiché sur la deuxième zone de texte. Je voudrais que la deuxième zone de texte se décale * automatiquement * vers le bas lorsqu'un message d'erreur s'affiche pour la première zone de texte (et redescende lorsque le message d'erreur disparaît). –

Répondre

10

il y a deux semaines, je faisais face à la même question .

J'ai trouvé une solution après avoir vu ce blog de Josh Smith.

http://joshsmithonwpf.wordpress.com/2008/10/08/binding-to-validationerrors0-without-creating-debug-spew/

L'astuce consiste à définir un DataTemplate pour rendre l'objet ValidationError puis utilisez un ContentPresenter pour afficher le message d'erreur. S'il n'y a pas d'erreur, le ContentPresenter ne sera pas affiché. Ci-dessous, j'ai partagé le code de l'exemple d'application que j'ai créé.

Without errorsWith errors

Voici le XAML:

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     SizeToContent="WidthAndHeight" 
     Title="MainWindow"> 
    <StackPanel Margin="5"> 
     <StackPanel.Resources> 
      <DataTemplate DataType="{x:Type ValidationError}"> 
       <TextBlock Text="{Binding ErrorContent}" Foreground="White" Background="Red" VerticalAlignment="Center" FontWeight="Bold"/> 
      </DataTemplate> 
     </StackPanel.Resources> 
     <TextBox Name="TextBox1" Text="{Binding Text1, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/> 
     <ContentPresenter Content="{Binding ElementName= TextBox1, Path=(Validation.Errors).CurrentItem}" HorizontalAlignment="Left"/> 

     <TextBox Name="TextBox2" Text="{Binding Text2, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/> 
     <ContentPresenter Content="{Binding ElementName= TextBox2, Path=(Validation.Errors).CurrentItem}" HorizontalAlignment="Left"/> 
     <Button Content="Validate" Click="Button_Click"/> 
    </StackPanel> 
</Window> 

Le fichier code-behind:

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     private ViewModel _ViewModel = null; 

     public MainWindow() 
     { 
      InitializeComponent(); 
      _ViewModel = new ViewModel(); 
      DataContext = _ViewModel; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      _ViewModel.Validate = true; 
      _ViewModel.OnPropertyChanged("Text1"); 
      _ViewModel.OnPropertyChanged("Text2"); 
     } 
    } 
} 

ViewModel:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 

namespace WpfApplication1 
{ 
    public class ViewModel : INotifyPropertyChanged, IDataErrorInfo 
    { 
     private string _Text1; 
     public string Text1 
     { 
      get { return _Text1; } 
      set 
      { 
       _Text1 = value; 
       OnPropertyChanged("Text1"); 
      } 
     } 

     private string _Text2; 
     public string Text2 
     { 
      get { return _Text2; } 
      set 
      { 
       _Text2 = value; 
       OnPropertyChanged("Text2"); 
      } 
     } 

     public bool Validate { get; set; } 

     #region INotifyPropertyChanged Implemenation 
     public event PropertyChangedEventHandler PropertyChanged; 

     public void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
     #endregion 

     #region IDataErrorInfo Implementation 
     public string Error 
     { 
      get { return null; } 
     } 

     public string this[string columnName] 
     { 
      get 
      { 
       string errorMessage = string.Empty; 
       if (Validate) 
       { 
        switch (columnName) 
        { 
         case "Text1": 
          if (Text1 == null) 
           errorMessage = "Text1 is mandatory."; 
          else if (Text1.Trim() == string.Empty) 
           errorMessage = "Text1 is not valid."; 
          break; 
         case "Text2": 
          if (Text2 == null) 
           errorMessage = "Text2 is mandatory."; 
          else if (Text2.Trim() == string.Empty) 
           errorMessage = "Text2 is not valid."; 
          break; 
        } 
       } 
       return errorMessage; 
      } 
     } 
     #endregion 
    } 
} 
+0

Merci pour la réponse. J'avais oublié de vérifier pour voir s'il y avait des réponses. L'échantillon que vous avez fourni a fait exactement ce que j'essayais d'accomplir. –

+0

Merci pour ce petit bijou. Exactement ce que je cherchais. Ne pas trouver de bons exemples +1 – Andez