BindingGroup с несколькими (ошибочными) ValidationRules - PullRequest
1 голос
/ 20 июля 2010

Я столкнулся с проблемой сегодня на работе, где у меня есть BindingGroup, у которого есть несколько ValidationRule с, которые терпят неудачу одновременно.Проблема в том, что я ArgumentException пузырится от BindingGroup.ValidateWithoutUpdate, когда я пытаюсь определить, есть ли какие-либо ошибки (т.е. установить CanExecute для команды false).

IМне удалось отнести его к следующему примеру (извините, он все еще пересекает несколько источников, но я вложил все соответствующие части, которые должны быть скопированы / вставлены в новый проект WPF):

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

По сути, моя проблема заключается в том, что если TestRule1 и 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` требует быть уникальным.

По общему признанию, этот пример надуман, однако он отлично демонстрирует мою реальную проблему, которой нет.(У меня есть 2 абсолютно независимых ValidationRule, которые работают с различными атрибутами одного и того же бизнес-объекта, и было бы бессмысленно объединять их в один ValidationRule).Кроме того, каждый пример использования BindingGroup, который я могу найти, только когда-либо демонстрирует использование одного ValidationRule, но конструкция явно поддерживает и принимает несколько правил, хотя, по-видимому, до тех пор, пока в один момент времени происходит сбой только одного.

Я делаю что-то не так, или это похоже на ошибку в реализации BindingGroup, как я склонен думать в настоящее время.

Для чего это стоит, я использую VS2008с .Net 3.5 SP1.

1 Ответ

2 голосов
/ 20 июля 2010

Он будет работать так, как вы ожидаете, если вы запустите его в .NET 4.0, поэтому похоже, что это действительно ошибка, и она будет исправлена ​​в следующем выпуске.

...