2016-12-07 47 views
1

我试图使图标,工具提示或聊天窗口出现在字段中,当用户尝试输入比字段应该接受的更长的字符串时。我已经广泛搜索这个,我很惊讶,这似乎没有简单的解决方案。我发现简单的解决方案可以在输入无效时更改字段外观,但不会发出警告并在字段中保留合法的先前值。如何实现这一目标?字段中的长度验证触发器错误图标

+1

这是一个伟大的想法,尤其是部分:“保留在该领域的法律原先的值”。你遇到了什么具体问题(提示:问题中没有问号)? – Sinatr

+0

因此,像['ErrorTemplate'](https://www.codeproject.com/tips/690130/simple-validation-in-wpf)? –

回答

0

正确的方法是使用ErrorTemplateValidationRule s。

首先你需要一个ValidationRule,在你的情况下,检查一个字符串的长度。

public class StringLengthRule : ValidationRule 
{ 
    public int MaxLength { get; set; } 

    public override ValidationResult Validate(object value, CultureInfo cultureInfo) 
    { 
     if (((string)value).Length > MaxLength) 
      return new ValidationResult(false, "Input too long!"); 
     return new ValidationResult(true, null); 
    } 
} 

你可以附加到你的观点的结合,例如:根据您的样式/模板,这将是这个样子

<TextBox> 
    <TextBox.Text> 
     <Binding RelativeSource="{RelativeSource AncestorType=local:MainWindow}" 
       UpdateSourceTrigger="PropertyChanged" <!-- or LostFocus --> 
       Path="Text"> 
      <Binding.ValidationRules> 
       <local:StringLengthRule MaxLength="15"/> 
      </Binding.ValidationRules> 
     </Binding> 
    </TextBox.Text> 
</TextBox> 

: (我已经包括了样式和模板在这个答案的底部)

Error Template

这将为内部错误工作了。如果您绑定到一个int例如:

Example 2

您可以使用相同的验证,以检查是否所有输入都是关闭对话框之前有效。

public static class ValidationHelper 
{ 
    public static bool IsValid(DependencyObject obj) 
    { 
     // The dependency object is valid if it has no errors and all 
     // of its children (that are dependency objects) are error-free. 
     return !Validation.GetHasError(obj) && 
     LogicalTreeHelper.GetChildren(obj) 
     .OfType<DependencyObject>() 
     .All(IsValid); 
    } 

    public static bool ShowValidHint(DependencyObject dependencyObject) 
    { 
     if (IsValid(dependencyObject)) return true; 

     MessageBox.Show(Strings.WarningInput, Strings.InputError, MessageBoxButton.OK, MessageBoxImage.Warning); 
     return false; 
    } 
} 

用法:

private void btnOk_Click(object sender, RoutedEventArgs e) 
{ 
    ((Button)sender).Focus(); 
    if (ValidationHelper.ShowValidHint(this)) 
     DialogResult = true; 
    else 
     // show error 
} 

对于保留法律前值一部分。最好通过PropertyMetadataPropertyChangedCallbackCoerceValueCallback或(如果您使用INotifyPropertyChanged代替)属性设置器完成。我个人会建议反对它。如果您更改该值,该值将再次有效,而键入查看键盘的人可能不知道他们做错了什么。


不记得我从哪里得到这个模板,但我一直在使用它的例子这样的年龄。

控制模板

<ControlTemplate x:Key="TextBoxErrorTemplate"> 
    <StackPanel Orientation="Horizontal"> 
     <!-- Defines TextBox outline border and the ToolTipCorner --> 
     <Border x:Name="border" BorderThickness="1.25" BorderBrush="#FFDC000C"> 
      <Grid> 
       <Polygon x:Name="toolTipCorner" Grid.ZIndex="2" Margin="-1" Points="9,9 9,0 0,0" Fill="#FFDC000C" HorizontalAlignment="Right" 
        VerticalAlignment="Top" IsHitTestVisible="True"/> 
       <Polyline Grid.ZIndex="3" Points="10,10 0,0" Margin="-1" HorizontalAlignment="Right" StrokeThickness="1.5" 
           StrokeEndLineCap="Round" StrokeStartLineCap="Round" Stroke="White" VerticalAlignment="Top" IsHitTestVisible="True"/> 
       <AdornedElementPlaceholder x:Name="adorner"/> 
      </Grid> 
     </Border> 
     <!-- Defines the Popup --> 
     <Popup x:Name="placard" AllowsTransparency="True" PopupAnimation="Fade" Placement="Top" PlacementTarget="{Binding ElementName=toolTipCorner}" PlacementRectangle="10,-1,0,0"> 
      <!-- Used to reposition Popup when dialog moves or resizes --> 
      <Popup.Style> 
       <Style TargetType="{x:Type Popup}"> 
        <Style.Triggers> 
         <!-- Shows Popup when TextBox has focus --> 
         <DataTrigger Binding="{Binding ElementName=adorner, Path=AdornedElement.IsFocused}" Value="True"> 
          <Setter Property="IsOpen" Value="True"/> 
         </DataTrigger> 
         <!-- Shows Popup when mouse hovers over ToolTipCorner --> 
         <DataTrigger Binding="{Binding ElementName=toolTipCorner, Path=IsMouseOver}" Value="True"> 
          <Setter Property="IsOpen" Value="True"/> 
         </DataTrigger> 
         <!-- Hides Popup when window is no longer active --> 
         <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=IsActive}" Value="False"> 
          <Setter Property="IsOpen" Value="False"/> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </Popup.Style> 
      <Border x:Name="errorBorder" 
      Background="#FFDC000C" 
      Margin="0,0,8,8" 
      Opacity="1" 
      CornerRadius="4" 
      IsHitTestVisible="False" 
      MinHeight="24" 
      MaxWidth="267"> 
       <Border.Effect> 
        <DropShadowEffect ShadowDepth="4" 
          Color="Black" 
          Opacity="0.6" 
          Direction="315" 
          BlurRadius="4"/> 
       </Border.Effect> 
       <TextBlock Text="{Binding ElementName=adorner, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}" 
       Foreground="White" 
       Margin="8,3,8,3" 
       TextWrapping="Wrap"/> 
      </Border> 
     </Popup> 
    </StackPanel> 
</ControlTemplate> 

样式

<Style TargetType="{x:Type TextBox}"> 
    <Setter Property="Validation.ErrorTemplate" Value="{StaticResource TextBoxErrorTemplate}"/> 
</Style> 
+0

我一直对WPF中简单问题的解决方案的冗长感到惊叹。只有我吗?我可以考虑如何用几行代码(十个顶点)在Java中解决这个问题。 MVVM和WPF是一个代码页面。 –

+0

我需要一些时间来调查这是否能解决问题。我会在做一些工作后更新。谢谢。 –

+0

@ÁrniSt.Sigurðsson所以...有帮助吗? –