控件中的控件模板影响UI验证中的其他控件

时间:2018-03-31 08:23:57

标签: wpf controltemplate inotifydataerrorinfo

我非常精通WPF,但对实现UI验证的领域很陌生,我需要确保某些值已准备好保存到数据库。在我非常大的应用程序中,我有很多不同类型的验证,其中包括简单的单一(TextBox需要一个值或最小字符),(必须选择项目),(必须至少选择一个选项),依此类推。 我已经使用INotifyDataErrorInfo实现了验证,这非常有效,除了一些问题,我正在圈子里并需要一些指导。事实上,这可能更多是造型问题。以下只是我的一个问题,但如果我解决这个问题,那么它可以解决其他问题,所以我现在就坚持这个: 我有一组单选按钮控件,其中一个必须由用户选择,但我不希望任何选择默认,因此被迫做出选择。在他们选择一个之前,需要在堆叠面板中的单选按钮周围显示红色边框。因为这是我想在我有一组控件的几个地方做的事情,我认为最好创建一个名为ErrorBorderControl的Border控件,它使用属性管理数据错误,然后将项目弹出到此控件中。我在这个名为ValidationObject的类型对象上创建一个DependecyProperty,它只需要一个可以测试的属性来查看是否有错误。这完美地工作,未选中时显示红色边框,选择时不显示。到目前为止很棒。但是,ErrorBorderControl中定义的ControlTemplate会导致UI中所有其他基于边框的控件,包括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>

输出:

Invalid Selection

请注意,虽然模板虽然在用户控件中定义,但它正在影响其他控件中的其他Border控件。看看我做出选择的时间:

Valid Selection

以红色表示的控件不参与验证。另一个控件中的控件模板如何影响所有边框?我只是不明白。我需要做的是定义一个模板,我可以将其应用于我希望仅应用于控件的控件,并且能够重复使用它。

0 个答案:

没有答案