Шаблон элемента управления в элементе управления, влияющий на другие элементы управления при проверке пользовательского интерфейса
Я достаточно опытен в WPF, но плохо знаком с областью реализации валидации пользовательского интерфейса, где мне нужно убедиться, что определенные значения готовы для сохранения в базе данных. В моем очень большом приложении у меня есть много разных типов проверки, в том числе простой сингл (TextBox требует значения или минимум символов), (должен быть выбран элемент), (должен быть выбран хотя бы один параметр) и так далее. Я реализовал проверку с использованием INotifyDataErrorInfo, и это работает очень хорошо, за исключением нескольких проблем, с которыми я сталкиваюсь кругами и нуждаюсь в некотором руководстве. На самом деле, это скорее вопрос стиля. Следующее - только одна из моих проблем, но если я решу это, то это может решить другие, так что пока я буду придерживаться этого: у меня есть набор переключателей, где пользователь должен выбрать один, но я не хочу любой должен быть выбран по умолчанию, поэтому вынужден сделать выбор. Пока они не выберут одну, вокруг переключателей, которые находятся на панели стека, должна отображаться красная рамка. Поскольку это то, что я хочу сделать в нескольких местах, где у меня есть группа элементов управления, я подумал, что было бы хорошо создать элемент управления Border с именем ErrorBorderControl, который управляет ошибками данных с использованием свойства, а затем вставлять элементы в этот элемент управления. Я создаю DependecyProperty для этого элемента управления с именем ValidationObject типа object, который просто принимает свойство, которое можно проверить, чтобы увидеть, есть ли ошибка. Это работает отлично, и красная рамка отображается, когда она не выбрана, а не когда выбрана. Отлично, пока. Тем не менее, ControlTemplate, определенный в ErrorBorderControl, кровоточит для всех других основанных на границе элементов управления в пользовательском интерфейсе, включая границу вокруг элементов управления RadioButton. Я много работаю со стилями и понимаю сферу, но это очень странно. Ниже приведено то, что я сделал, хотя в качестве первой попытки он был очень прост:
Пользовательский контроль:
<UserControl
x:Class="Itec.Common.Wpf.CustomControls.Controls.ErrorBorderControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<!--
Provides a border around grouped controls that needs error feedback
-->
<Border>
<!-- Style -->
<Border.Style>
<Style
TargetType="{x:Type Border}"
x:Name="TheTemplate">
<!-- Error template definition -->
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<!-- Adorner for the error visual -->
<AdornedElementPlaceholder>
<!-- Simple border around the control -->
<Border
BorderBrush="#ec7063"
BorderThickness="1"/>
</AdornedElementPlaceholder>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Border.Style>
</Border>
</UserControl>
Код позади:
/// <summary>
/// Interaction logic for ErrorBorderControl.xaml
/// </summary>
public partial class ErrorBorderControl : UserControl
{
#region Dependency Properties
/// <summary>
/// The validation object property
/// </summary>
public static readonly DependencyProperty ValidationObjectProperty =
DependencyProperty.Register("ValidationObject", typeof(object), typeof(ErrorBorderControl),
new FrameworkPropertyMetadata(OnValidationObjectChanged));
#endregion Dependency Properties
#region Ctors
/// <summary>
/// Initializes a new instance of the <see cref="ErrorBorderControl"/> class.
/// </summary>
public ErrorBorderControl()
{
InitializeComponent();
}
#endregion Ctors
#region Public Properties
/// <summary>
/// Gets or sets the validation object.
/// </summary>
/// <value>The validation object.</value>
public object ValidationObject
{
get { return (object)GetValue(ValidationObjectProperty); }
set { SetCurrentValue(ValidationObjectProperty, value); }
}
#endregion Public Properties
#region Private Methods
/// <summary>
/// Raises when the ValidationObject property value changes
/// </summary>
/// <param name="d">The d.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnValidationObjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ErrorBorderControl)d).ValidationObject = e.NewValue;
}
#endregion Private Methods
}
Реализация:
<!-- Owner type -->
<itc:ErrorBorderControl
Grid.Row="1"
ValidationObject="{Binding Path=RecordType, ValidatesOnNotifyDataErrors=True}">
<StackPanel
Orientation="Horizontal">
<!-- Owner -->
<itc:ItecRadioButton
Content="{DynamicResource Language.SingleLine.Owner}"
Margin="0,4,4,4"
IsChecked="{Binding Path=RecordType, Converter={itc:EnumToBooleanConverter EnumValue={x:Static recordOwners:RecordOwnerRecordType.Owner}}}"/>
<!-- FAO -->
<itc:ItecRadioButton
Content="{DynamicResource Language.SingleLine.FAO}"
Margin="0,4,4,4"
IsChecked="{Binding Path=RecordType, Converter={itc:EnumToBooleanConverter EnumValue={x:Static recordOwners:RecordOwnerRecordType.Fao}}}"/>
<!-- Account Manager -->
<itc:ItecRadioButton
Content="{DynamicResource Language.SingleLine.Account_Manager}"
Margin="0,4,4,4"
IsChecked="{Binding Path=RecordType, Converter={itc:EnumToBooleanConverter EnumValue={x:Static recordOwners:RecordOwnerRecordType.AccountManager}}}"/>
<!-- Watcher -->
<itc:ItecRadioButton
Content="{DynamicResource Language.SingleLine.Watcher}"
Margin="0,4,4,4"
IsChecked="{Binding Path=RecordType, Converter={itc:EnumToBooleanConverter EnumValue={x:Static recordOwners:RecordOwnerRecordType.Watcher}}}"/>
</StackPanel>
</itc:ErrorBorderControl>
Выход:
Обратите внимание, что шаблон выглядит так, как будто он определен внутри пользовательского элемента управления, но влияет на другие элементы управления Border внутри другого элемента управления. Посмотрите, когда я сделал выбор:
Элементы управления, оставленные красным, не участвуют в проверке. Как шаблон элемента управления в другом элементе управления влияет на все границы? Я просто не понимаю Что мне нужно сделать, это определить шаблон, который я могу применить к элементу управления, к которому я хочу, чтобы он применялся только, и иметь возможность его повторного использования.