2016-12-07 75 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所以...有幫助嗎? –