Вот (несколько) урезанный пример кода, который у меня есть, который пытается использовать 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) для правильной установки начальных состояний правила при установлении контекста данных?