Возможно ли, чтобы BindingGroup.CommitEdit / ValidateWithoutUpdate всегда запускал все правила проверки Binding? - PullRequest
3 голосов
/ 12 апреля 2011

Вот (несколько) урезанный пример кода, который у меня есть, который пытается использовать BindingGroup:

XAML:

<Window x:Class="BindingGroupQuandary.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:BindingGroupQuandary"
        Title="Binding Group Test" Width="400" Height="400" MinWidth="400" MinHeight="400">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition/>            
            <RowDefinition/>
        </Grid.RowDefinitions>
        <GroupBox Header="Items">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>            
                <ListView Name="dataList">
                    <ListView.View>
                        <GridView>
                            <GridView.Columns>
                                <GridViewColumn Header="First Property" DisplayMemberBinding="{Binding FirstProperty}" />
                                <GridViewColumn Header="Second Property" DisplayMemberBinding="{Binding SecondProperty}" />                                
                            </GridView.Columns>
                        </GridView>
                    </ListView.View>
                </ListView>
                <Button Grid.Row="1" Content="Add Item" Click="add_Click" HorizontalAlignment="Left" Margin="0,5,0,5" />
            </Grid>
        </GroupBox>        
        <GroupBox Grid.Row="1" Name="editControls" Header="Edit Item">
            <GroupBox.BindingGroup>
                <BindingGroup Name="editItemBindings"/>                    
            </GroupBox.BindingGroup>            
            <StackPanel>
                <Label Content="First Property (Required)"/>
                <TextBox>
                    <TextBox.Text>
                        <Binding Path="FirstProperty">
                            <Binding.ValidationRules>
                                <local:NotEmptyValidationRule ValidationStep="RawProposedValue"/>
                            </Binding.ValidationRules>
                        </Binding>
                    </TextBox.Text>
                </TextBox>
                <Label Content="Second Property (Required)"/>
                <TextBox>
                    <TextBox.Text>
                        <Binding Path="SecondProperty">
                            <Binding.ValidationRules>
                                <local:NotEmptyValidationRule ValidationStep="RawProposedValue"/>
                            </Binding.ValidationRules>
                        </Binding>
                    </TextBox.Text>
                </TextBox>                
                <Button Content="Commit" Click="commit_Click" HorizontalAlignment="Left" Margin="0,10,0,0"/>
            </StackPanel>            
        </GroupBox>
    </Grid>
</Window>

Код-за:

using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;

namespace BindingGroupQuandary
{
    class SomeData
    {
        public string FirstProperty { get; set; }
        public string SecondProperty { get; set; }        
    }

    class NotEmptyValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            string textValue = (value as string);

            ValidationResult result;

            if (string.IsNullOrWhiteSpace(textValue))
            {
                result = new ValidationResult(false, "The field must contain a text value and cannot be empty.");
            }
            else
            {
                result = new ValidationResult(true, null);
            }

            return result;
        }
    }

    public partial class MainWindow : Window
    {        
        private ObservableCollection<SomeData> _items = new ObservableCollection<SomeData>();

        public MainWindow()
        {
            InitializeComponent();

            dataList.ItemsSource = _items;
        }

        private void add_Click(object sender, RoutedEventArgs e)
        {
            editControls.DataContext = (new SomeData() { FirstProperty = "This property has an initial value." });
            editControls.BindingGroup.BeginEdit();            
        }

        private void commit_Click(object sender, RoutedEventArgs e)
        {
            SomeData current = editControls.DataContext as SomeData;

            if (current != null)
            {                
                if (editControls.BindingGroup.CommitEdit())
                {
                    _items.Add(current);

                    editControls.DataContext = null;
                }
            }
        }
    }
}

Эффект, который я ищу, таков:

  • Я нажимаю «Добавить элемент», чтобы привязать объект к элементам управления редактирования в нижней половине окна (которые обычно не видны, пока контекст данных не будет предоставлен в реальном приложении).
  • Я намеренно не устанавливал ValidatesOnTargetUpdated в привязке к любому из свойств, потому что я пока не хочу показывать какие-либо средства сообщения об ошибках; текст поля уже намекает на то, что поля обязательны для заполнения.
  • Когда я нажимаю кнопку «Фиксация», я хочу, чтобы группа BindingGroup повторно проверила все правила валидации, чтобы перехватить все поля, которые еще не заполнены, и отобразить средства сообщения об ошибках в этой точке.

К сожалению, используя приведенный выше пример кода, если я нажимаю «Добавить», а затем сразу нажимаю «Подтвердить», не заполняя поле «Второе свойство» и не изменяя что-либо, группа привязки вообще не вызывает мои правила проверки; CommitEdit возвращает значение «истина», и объект передается в базовую коллекцию. Вызов ValidateWithoutUpdate также просто возвращает «true». Мои тесты с приложением показывают, что CommitEdit и ValidateWithoutUpdate фактически вызывают только правила проверки, где:

  • В настоящее время правило неверно / недействительно.
  • Правило в настоящее время действует, но значение изменилось.

Методы, похоже, не переоценивают действительные правила, для которых значение не изменилось. Я полагаю, что такое поведение имеет смысл (и, возможно, это просто общее обязательное поведение?), Но, похоже, оно противоречит документации, в которой говорится, для CommitEdit:

Запускает все объекты ValidationRule и обновляет источники привязки, если все правила проверки успешны.

Я полагаю, что правила проверки, упомянутые в этом утверждении, могут ссылаться только на правила верхнего уровня в самой BindingGroup, а не на правила проверки в отдельных привязках. В любом случае, мой реальный вопрос: возможно ли заставить BindingGroup перепроверить все правила валидации в этом примере; если нет, могу ли я сделать это напрямую с помощью коллекции BindingExpressions? Или я должен просто сдаться и положиться на ValidatesOnTargetUpdated (возможно, в сочетании с менее ярким шаблоном adorner) для правильной установки начальных состояний правила при установлении контекста данных?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...