如果选中复选框,则启用ValidationRule

时间:2012-07-18 10:05:00

标签: wpf vb.net validation

我想验证一些控件,但只有选中了我的复选框。 (在此示例中,我只显示一个要验证的文本框)

我尝试使用BindingGroup,但这意味着该复选框也经过验证,这会给我错误的结果。

现在我尝试使用MultiBinding:

<CheckBox Name="chkUseLqv"
              Grid.Row="6"
              Grid.Column="0"
              Margin="0,0,8,0"
              HorizontalAlignment="Right"
              VerticalAlignment="Center"
              Content="Use LQV"
              IsChecked="{Binding LqvConfigurationEnabled}" />

[...]

<GroupBox Grid.Row="1"
          Grid.RowSpan="6"
          Grid.Column="4"
          Margin="5"
          Header="LQV Configuration"
          IsEnabled="{Binding LqvConfigurationEnabled}">
  <Grid>
    <TextBox Name="txtLqvDatabaseServer"
             Grid.Row="1"
             Grid.Column="1"
             VerticalAlignment="Center"
             Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}">
      <TextBox.Text>
        <MultiBinding Converter="{Converters:LqvConfigurationMultiBindingConverter}" UpdateSourceTrigger="PropertyChanged">
          <MultiBinding.ValidationRules>
            <LocalValidationRules:LqvDatabaseServerValidator />
          </MultiBinding.ValidationRules>
          <Binding ElementName="chkUseLqv" Path="IsChecked" />
          <Binding Path="LqvDatabaseServer" />
        </MultiBinding>
      </TextBox.Text>
    </TextBox>
  </Grid>
</GroupBox>

我的验证员:

Imports System.Text.RegularExpressions

Namespace ValidationRules
  Public Class LqvDatabaseServerValidator
    Inherits ValidationRule

    Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As System.Globalization.CultureInfo) As System.Windows.Controls.ValidationResult
      Dim useLqv = CType(value, Object()).OfType(Of Boolean).First()
      Dim valueFromSource = CType(value, Object()).OfType(Of String).FirstOrDefault()

      If useLqv Then
        If String.IsNullOrEmpty(valueFromSource) Then
          Return New ValidationResult(False, "This field is required!")
        End If

        If Not (
          Regex.IsMatch(valueFromSource, "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$") OrElse
          Regex.IsMatch(valueFromSource, "^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$")
          ) Then
          Return New ValidationResult(False, "Invalid input!")
        End If
      End If

      Return ValidationResult.ValidResult
    End Function
  End Class
End Namespace

转换器:

Imports System.Windows.Markup

Namespace Converters
  Public Class LqvConfigurationMultiBindingConverter
    Inherits MarkupExtension
    Implements IMultiValueConverter

    Public Sub New()
    End Sub

    Private _orig As Object()

    Public Function Convert(ByVal values() As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IMultiValueConverter.Convert
      _orig = values
      Return values.OfType(Of String).FirstOrDefault()
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetTypes() As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object() Implements System.Windows.Data.IMultiValueConverter.ConvertBack
      Return _orig
    End Function

    Public Overrides Function ProvideValue(ByVal serviceProvider As System.IServiceProvider) As Object
      Return New LqvConfigurationMultiBindingConverter()
    End Function
  End Class
End Namespace

但它不起作用。你能救我吗?

1 个答案:

答案 0 :(得分:0)

我是这样做的:

在资源中定义样式:

<Style x:Key="lqvDependingFields" TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate">
      <Setter.Value>
        <ControlTemplate />
      </Setter.Value>
    </Setter>
    <Style.Triggers>
      <DataTrigger Binding="{Binding ElementName=chkUseLqv, Path=IsChecked}" Value="true">
        <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}" />
      </DataTrigger>
    </Style.Triggers>
  </Style>

有一个复选框:

<CheckBox Name="chkUseLqv"
          Grid.Row="6"
          Grid.Column="0"
          Margin="0,0,8,0"
          HorizontalAlignment="Right"
          VerticalAlignment="Center"
          Content="Use LQV"
          IsChecked="{Binding LqvConfigurationEnabled}" />

使用控件上的样式:

    <TextBox Name="txtLqvDatabaseServer"
             Grid.Row="1"
             Grid.Column="1"
             VerticalAlignment="Center"
             DependencyProperties:AttachedWindowProperties.HasValidationError="{Binding LqvDatabaseServerValidationError}"
             Style="{StaticResource lqvDependingFields}">
      <TextBox.Text>
        <Binding NotifyOnSourceUpdated="True"
                 Path="LqvDatabaseServer"
                 UpdateSourceTrigger="PropertyChanged">
          <Binding.ValidationRules>
            <LocalValidationRules:LqvDatabaseServerValidator ValidatesOnTargetUpdated="True" />
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>

依赖属性:

#Region "HasValidationErrorProperty"

    Public Shared ReadOnly HasValidationErrorProperty As DependencyProperty =
      DependencyProperty.RegisterAttached("HasValidationError", GetType(Boolean), GetType(AttachedWindowProperties),
                                          New FrameworkPropertyMetadata(False, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                                        Nothing, AddressOf CoerceHasValidationError))

    Public Shared Function GetHasValidationError(ByVal d As DependencyObject) As Boolean
      Return CBool(d.GetValue(HasValidationErrorProperty))
    End Function

    Public Shared Sub SetHasValidationError(ByVal d As DependencyObject, ByVal value As Boolean)
      d.SetValue(HasValidationErrorProperty, value)
    End Sub

    Private Shared Function CoerceHasValidationError(ByVal d As DependencyObject, ByVal baseValue As Object) As Object
      Dim result As Boolean = CBool(baseValue)

      If BindingOperations.IsDataBound(d, HasValidationErrorProperty) Then
        If GetHasErrorDescriptor(d) Is Nothing Then
          Dim desc = DependencyPropertyDescriptor.FromProperty(Validation.HasErrorProperty, d.GetType)
          desc.AddValueChanged(d, AddressOf OnHasErrorChanged)
          SetHasErrorDescriptor(d, desc)
          result = Validation.GetHasError(d)
        End If
      Else
        If GetHasErrorDescriptor(d) IsNot Nothing Then
          Dim desc As DependencyPropertyDescriptor = GetHasErrorDescriptor(d)
          desc.RemoveValueChanged(d, AddressOf OnHasErrorChanged)
          SetHasErrorDescriptor(d, Nothing)
        End If
      End If

      Return result
    End Function

    Private Shared Sub OnHasErrorChanged(ByVal sender As Object, ByVal e As EventArgs)
      Dim d As DependencyObject = TryCast(sender, DependencyObject)

      If d IsNot Nothing Then
        d.SetValue(HasValidationErrorProperty, d.GetValue(Validation.HasErrorProperty))
      End If
    End Sub

    Private Shared ReadOnly HasErrorDescriptorProperty As DependencyProperty =
      DependencyProperty.RegisterAttached("HasErrorDescriptor", GetType(DependencyPropertyDescriptor), GetType(AttachedWindowProperties))

    Private Shared Function GetHasErrorDescriptor(ByVal d As DependencyObject) As DependencyPropertyDescriptor
      Return CType(d.GetValue(HasErrorDescriptorProperty), DependencyPropertyDescriptor)
    End Function

    Private Shared Sub SetHasErrorDescriptor(ByVal d As DependencyObject, ByVal value As DependencyPropertyDescriptor)
      d.SetValue(HasErrorDescriptorProperty, value)
    End Sub

#End Region

LqvDatabaseServerLqvDatabaseServerValidationErrors是我的ViewModel中的属性。