2011-02-23 68 views
3

在我的WPF應用程序中,我想只在用戶編輯/輸入/關注控件後才顯示驗證裝飾。通過這種方式,用戶有機會向該字段提供有效的輸入,並且只有在他們選擇不輸入時,纔會顯示驗證。WPF驗證裝飾 - 只顯示控件是否持有焦點

我們要鼓勵場完成這樣表示必填字段,當窗體第一次打開可以規避在緊接用戶將傾向於剛剛完成他們需要什麼,以便擺脫大紅色的驗證錯誤也可能會阻止表單的流動。

有沒有辦法知道控件是否已經成爲焦點?附屬物可能會工作嗎?

如果它有助於提供更具體的迴應:這裏是我目前的驗證樣式,顯示紅色邊框[如果控件有邊框],並帶有錯誤消息的工具提示的小驚歎號(非常標準):

<Style TargetType="Control"> 
    <Style.Triggers> 
     <Trigger Property="Validation.HasError" Value="true"> 
      <Setter Property="ToolTip" 
        Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
        Path=(Validation.Errors).CurrentItem.ErrorContent}"/> 

      <Setter Property="Validation.ErrorTemplate"> 
       <Setter.Value> 
        <ControlTemplate> 
         <DockPanel LastChildFill="true"> 
          <Image Source="../Resources/Icons/Error.ico" Margin="4" Width="15" ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}" /> 
          <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" > 
           <Border BorderBrush="red" BorderThickness="1" Visibility="{Binding ElementName=customAdorner, Path=AdornedElement.BorderThickness, Converter={StaticResource hasBorderToVisibilityConverter}}" /> 
          </AdornedElementPlaceholder> 
         </DockPanel> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Trigger> 
     <Trigger Property="IsVisible" Value="False"> 
      <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

回答

8

您可以將附加行​​爲與附加屬性結合起來執行此操作。該附加的行爲,ObserveFocus將訂閱GotFocus事件,在事件處理程序設置HasHeldFocus附加屬性以True

它可以用來設置屬性,一個ViewModel這樣

<Button local:HasHeldFocusBehavior.ObserveFocus="True" 
     local:HasHeldFocusBehavior.HasHeldFocus="{Binding HasHeldFocus, 
                  Mode=OneWayToSource}"/> 

這裏是一個例如它如何可以用來改變ButtonBackground一旦它一直專注

<Style TargetType="Button"> 
    <Setter Property="Background" Value="Red"/> 
    <Setter Property="local:HasHeldFocusBehavior.ObserveFocus" Value="True"/> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, 
             Path=(local:HasHeldFocusBehavior.HasHeldFocus)}" 
         Value="True"> 
      <Setter Property="Background" Value="Green"/> 
     </DataTrigger> 
    </Style.Triggers> 
</Style> 

HasHeldFocusBehavior

public static class HasHeldFocusBehavior 
{ 
    public static readonly DependencyProperty ObserveFocusProperty = 
     DependencyProperty.RegisterAttached("ObserveFocus", 
              typeof(bool), 
              typeof(HasHeldFocusBehavior), 
              new UIPropertyMetadata(false, OnObserveFocusChanged)); 
    public static bool GetObserveFocus(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(ObserveFocusProperty); 
    } 
    public static void SetObserveFocus(DependencyObject obj, bool value) 
    { 
     obj.SetValue(ObserveFocusProperty, value); 
    } 
    private static void OnObserveFocusChanged(DependencyObject dpo, 
               DependencyPropertyChangedEventArgs e) 
    { 
     UIElement element = dpo as UIElement; 
     element.Focus(); 
     if ((bool)e.NewValue == true) 
     { 
      SetHasHeldFocus(element, element.IsFocused); 
      element.GotFocus += element_GotFocus; 
     } 
     else 
     { 
      element.GotFocus -= element_GotFocus; 
     } 
    } 
    static void element_GotFocus(object sender, RoutedEventArgs e) 
    { 
     UIElement element = sender as UIElement; 
     SetHasHeldFocus(element, true); 
    } 

    private static readonly DependencyProperty HasHeldFocusProperty = 
     DependencyProperty.RegisterAttached("HasHeldFocus", 
              typeof(bool), 
              typeof(HasHeldFocusBehavior), 
              new UIPropertyMetadata(false)); 
    public static void SetHasHeldFocus(DependencyObject element, bool value) 
    { 
     element.SetValue(HasHeldFocusProperty, value); 
    } 
    public static bool GetHasHeldFocus(DependencyObject element) 
    { 
     return (bool)element.GetValue(HasHeldFocusProperty); 
    } 
} 

更新

在你的情況,你可以用MultiTrigger

<Style TargetType="Control"> 
    <Style.Triggers> 
     <MultiDataTrigger> 
      <MultiDataTrigger.Conditions> 
       <Condition Binding="{Binding RelativeSource={RelativeSource Self}, 
              Path=(Validation.HasError)}" 
          Value="True"/> 
       <Condition Binding="{Binding RelativeSource={RelativeSource Self}, 
              Path=(local:HasHeldFocusBehavior.HasHeldFocus)}" 
          Value="True"/> 
      </MultiDataTrigger.Conditions> 
      <!-- Setters.. --> 
     </MultiDataTrigger> 
     <!-- ... --> 
    </Style.Triggers> 
</Style> 
+1

神奇更換Validation.HasError觸發!我確實將它改爲基於'LostFocus'而不是'GotFocus',但它工作得很完美。 – Reddog 2011-02-23 23:10:53

+0

@Reddog:好吧,好像我是通過其他方式得到它:)很高興聽到它的工作! – 2011-02-23 23:13:07