2010-07-20 3 views
1

J'ai rencontré un problème aujourd'hui au travail où j'ai un BindingGroup qui a plusieurs ValidationRule qui échouent simultanément. Le problème est, je reçois un ArgumentException bouillonnant à partir de BindingGroup.ValidateWithoutUpdate lorsque j'essaie de déterminer s'il y a des erreurs (à savoir pour définir le CanExecute sur une commande à false).BindingGroup avec plusieurs ValidationRules (en échec)

Je suis parvenu à distiller à l'exemple suivant (désolé, il traverse encore plusieurs sources, mais j'avons joint toutes les pièces pertinentes qui devraient être copier/pasteable dans un nouveau projet WPF):

fenêtre1 .xaml:

<Window 
    x:Class="BindingGroupTest.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:l="clr-namespace:BindingGroupTest" 
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" 
    Title="Window1" Height="300" Width="300"> 

    <Window.BindingGroup> 
     <BindingGroup Name="RootBindingGroup"> 
      <BindingGroup.ValidationRules> 
       <l:TestRule1 /> 
       <l:TestRule2 /> 
      </BindingGroup.ValidationRules> 
     </BindingGroup> 
    </Window.BindingGroup> 

    <StackPanel> 
     <TextBox Text="{Binding 
      Path=Name, 
      BindingGroupName=RootBindingGroup, 
      UpdateSourceTrigger=PropertyChanged, 
      diag:PresentationTraceSources.TraceLevel=High}" /> 
     <TextBox Text="{Binding 
      Path=Age, 
      BindingGroupName=RootBindingGroup, 
      UpdateSourceTrigger=PropertyChanged, 
      diag:PresentationTraceSources.TraceLevel=High}" /> 
     <Button Content="Validate" Click="DoValidate" /> 
    </StackPanel> 
</Window> 

Window1.xaml.cs:

using System; 
using System.Collections.Generic; 
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 BindingGroupTest 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      this.DataContext = new Person() 
      { 
       Name="Test", 
       Age=30, 
      }; 

      InitializeComponent(); 

      this.BindingGroup.BeginEdit(); 
     } 

     private void DoValidate(object sender, RoutedEventArgs e) 
     { 
      try 
      { 
       if (!this.BindingGroup.ValidateWithoutUpdate()) 
        MessageBox.Show("Validation failed!"); 
       else 
        MessageBox.Show("Validation passed!"); 
      } 
      catch (Exception ex) 
      { 
       var msg = "While validating, caught exception: " + ex.Message; 
       MessageBox.Show(msg); 
      } 
     } 
    } 
} 

Person.cs:

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

namespace BindingGroupTest 
{ 
    public class Person 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
    } 
} 

TestRule1.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 

namespace BindingGroupTest 
{ 
    public class TestRule1 : ValidationRule 
    { 
     public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) 
     { 
      var p = ((BindingGroup)value).Items[0] as Person; 
      if (p == null) 
       return ValidationResult.ValidResult; 

      if (p.Age < 0) 
       return new ValidationResult(false, "Surely, you've been born yet!"); 

      return ValidationResult.ValidResult; 
     } 
    } 
} 

TestRule2.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 

namespace BindingGroupTest 
{ 
    public class TestRule2 : ValidationRule 
    { 
     public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) 
     { 
      var p = ((BindingGroup)value).Items[0] as Person; 
      if (p == null) 
       return ValidationResult.ValidResult; 

      if (string.IsNullOrEmpty(p.Name)) 
       return new ValidationResult(false, "What, no name?"); 

      return ValidationResult.ValidResult; 
     } 
    } 
} 

Au fond, mon problème est que si les deux TestRule1 et TestRule2 fail, I get an ArgumentException bubbling up when I call this.BindingGroup.ValidateWithoutUpdate() with message "Cannot have duplicates in this Collection", parameter name: "validationError". I dug around through the implementation of BindingGroup , and it seems that it is using itself as the second parameter to ValidationError , which is the bindingInError parameter, which the underlying ValidationErrorCollection` doit être unique.

Certes, cet exemple est artificiel, mais il illustre parfaitement mon problème réel qui ne l'est pas. (J'ai 2, entièrement indépendants, ValidationRule s qui fonctionnent sur différents attributs du même objet métier, et il serait inutile de les réduire en un seul ValidationRule). De plus, chaque exemple que je peux trouver en utilisant BindingGroup démontre seulement l'utilisation d'un seul ValidationRule, mais la construction supporte clairement et accepte plusieurs règles, bien qu'apparemment, tant qu'un seul échoue à la fois. Est-ce que je fais quelque chose de mal, ou cela semble-t-il être un bug dans l'implémentation BindingGroup, comme je suis enclin à le penser actuellement.

Pour ce que ça vaut, j'utilise VS2008 avec .Net 3.5 SP1.

+0

Désolé, je ne sais pas pourquoi, mais malgré l'affichage dans la fenêtre d'édition, le haut de la déclaration de fenêtre dans Window1.xaml n'apparaît pas dans le code. La seule chose à noter est que l'espace de noms 'l' est défini comme étant" clr-namespace: BindingGroupTest ". –

+0

a fixé cela pour vous. Vous n'avez pas utilisé le bouton de code avec le code en surbrillance, donc cela n'a pas fonctionné correctement. – Femaref

+0

Ah, merci, @Femaref. –

Répondre

2

Cela fonctionnera comme vous l'attendez si vous l'exécutez dans .NET 4.0, il semble donc que c'était un bug et qu'il a été corrigé dans la prochaine version.

+0

Merci. Content de savoir que je ne deviens pas fou et que c'est corrigé en 4.0. J'ai travaillé autour d'elle en enveloppant des appels à 'BindingGroup.ValidateWithoutUpdate()' pour attraper le ArgumentException et en le traitant comme une validation échouée. Agaçant, mais réalisable jusqu'à ce que je suis autorisé à migrer vers 4.0. –