2012-04-24 26 views
13

我想要實現使用IDataErrorInfo界面我的WPF應用程序的驗證,我已經遇到了一個不那麼理想的情況。錯誤模板上面其他控件顯示,當它應該被隱藏

我有這個模板,用於當控件無法驗證

<ControlTemplate x:Key="errorTemplate"> 
    <DockPanel LastChildFill="true"> 
     <Border Background="Red" DockPanel.Dock="Right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10" 
            ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"> 
      <TextBlock Text="!" VerticalAlignment="Center" HorizontalAlignment="Center" FontWeight="Bold" Foreground="White" /> 
     </Border> 
     <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" > 
      <Border BorderBrush="red" BorderThickness="1" /> 
     </AdornedElementPlaceholder> 
    </DockPanel> 
</ControlTemplate> 

一切都順利,直到我試圖顯示一些驗證失敗,如顯示它上面的碼頭項目的控制上面:

Normal display Display when part of the control is hidden

我如何避免這種情況,並顯示在Dock項目我下面的錯誤模板,因爲它應該?

編輯

我發現我可以總結我TextBoxAdornerDecorator來解決這個問題,但我真的不想爲每個和我的應用程序的每個TextBox控制做到這一點。有沒有辦法用Style或其他方式設置它?

EDIT 2

我大概可以更改默認TextBox控件模板,包括一個AdornerDecorator,但我不改變任何的WPF的默認控件模板過於激烈。歡迎任何其他建議。

回答

10

好的,我發現了一個相對簡單的解決方案,並不強迫我改變任何控件模板。

相反裝潢每個TextBoxAdornerDecorator這樣

<StackPanel> 
    <AdornerDecorator> 
     <TextBox Text={Binding ...} /> 
    </AdornerDecorator> 
    <AdornerDecorator> 
     <TextBox Text={Binding ...} /> 
    </AdornerDecorator> 
</StackPanel> 

的我能有AdornerDecorator纏上了我的整個視圖,可達到相同的結果。

<AdornerDecorator> 
    <StackPanel> 
     <TextBox Text={Binding ...} /> 
     <TextBox Text={Binding ...} /> 
    </StackPanel> 
</AdornerDecorator> 

這樣我可以在每個視圖最多一次定義它。

0

我會使用一種風格,這裏有一個你可以輕鬆適應的例子。

注意,ErrorContent選自(Validation.Errors).CurrentItem.ErrorContent到來,而不是錯誤[0]。雖然兩者都能正常工作,但後者會吞噬您的輸出窗口,併吞入異常,如outlined here

<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}"> 
    <Setter Property="Margin" Value="0,0,16,0" /> 
    <Setter Property="VerticalAlignment" Value="Center" /> 
    <Setter Property="VerticalContentAlignment" Value="Center" /> 

    <!-- 
    Error handling 
    --> 
    <Setter Property="Validation.ErrorTemplate"> 
     <Setter.Value> 
      <ControlTemplate> 
       <DockPanel LastChildFill="True"> 
        <TextBlock DockPanel.Dock="Right" Text=" *" 
           Foreground="Red" FontWeight="Bold" FontSize="16" 
           ToolTip="{Binding ElementName=placeholder, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/> 
        <Border BorderBrush="Red" BorderThickness="1"> 
         <AdornedElementPlaceholder Name="placeholder"></AdornedElementPlaceholder> 
        </Border> 
       </DockPanel> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    <Style.Triggers> 
     <Trigger Property="Validation.HasError" Value="True"> 
      <Setter Property="Background" Value="LightYellow"/> 
     </Trigger> 
    </Style.Triggers> 
</Style> 
+1

我不看看這是如何解決任何事情。邊框仍顯示在碼頭項目上方。 – 2012-04-24 10:18:49

2

基於@AdiLester偉大的答案,如果你的控件是從基類派生,你不希望把AdornerDecorator在每個控制的XAML,然後走這條路:

public class MyBaseUserControl : UserControl 
{ 
    public MyBaseUserControl() 
    { 

    } 

    protected override void OnContentChanged(object oldContent, object newContent) 
    { 
     base.OnContentChanged(oldContent, newContent); 

     if (!(newContent is AdornerDecorator)) 
     { 
      this.RemoveLogicalChild(newContent); 

      var decorator = new AdornerDecorator(); 
      decorator.Child = newContent as UIElement; 

      this.Content = decorator; 
     } 
    } 
}