2012-07-02 112 views
0

我一直在试图解决这个问题。 :(WPF Validation.HasError设置文本框的边距

对于一个文本框,我有一个Validation.ErrorTemplate设置与文本框的右侧的图像,同时它有一个验证错误。

这个伟大的工程!但有一两件事我想这样做是调整或设置边距的文本框有错误,因此它适合在窗体上的文本框的空间。目前,图像流出的文本框区域之外。

我真正想要的是带有错误的文本框占据与textbox相同的空间。

这是我的XAML风格:

<Style TargetType="{x:Type TextBox}"> 
<Style.Resources> 
    <my:TextBoxWidthTransformConverter x:Key="TextBoxWidthTransformConverter"/> 
</Style.Resources> 
<Style.Triggers> 
    <Trigger Property="Validation.HasError" Value="true"> 
    <Setter Property="Foreground" Value="Red"/> 
    <Setter Property="Margin" Value="{Binding Converter={StaticResource TextBoxWidthTransformConverter}, RelativeSource={RelativeSource Self}}"/> 
    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}"/> 
    </Trigger> 
</Style.Triggers> 
<Setter Property="Validation.ErrorTemplate"> 
    <Setter.Value> 
    <ControlTemplate> 
     <StackPanel 
     Margin="{TemplateBinding Margin}" 
     Orientation="Horizontal" 
     RenderOptions.BitmapScalingMode="NearestNeighbor" 
     >    
     <AdornedElementPlaceholder 
      Grid.Column="1" 
      Grid.Row="1" 
      Name="controlWithError" 
      /> 
     <Border Width="2"/> 
     <Image 
      ToolTip="{Binding ElementName=controlWithError, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}" 
      Source="imagepath" 
      /> 
     </StackPanel> 
    </ControlTemplate> 
    </Setter.Value> 
</Setter> 

我使用一个转换器TextBoxWidthTransformConverter只是为了看看,如果我能得到一些事情发生,但在此之前我只是在数值使用“0,0,20,0”,无果。转换器不会触发,保证金不会改变。我使用Snoop来查看是否可以看到被触摸或更改的财产,但没有任何反应。

Margin属性是无法通过Validation.HasError属性进行更改的吗?

任何洞见将是美好的!

谢谢!

回答

0

希望能帮助任何可能遇到这个问题的人。

我仍然不确定为什么Margin属性在Validation.HasError触发器期间没有改变,但我发现了一个肮脏的工作。

解决方法是使用IValueConverter设置边距来劫持宽度属性与某些事件绑定(TextChanged和Unloading以清除事件)。我保留原来的保证金,在我的情况下,我只是担心右边距,通过利用TextBoxes标签属性。

public class TextBoxMarginConverter : IValueConverter 
{ 
    private const double TEXTBOX_MARGIN_RIGHT = 25.0; 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     if (value == null) 
     { 
     return double.NaN; 
     } 

     TextBox textBox = value as TextBox; 

     if (textBox == null) 
     { 
     return double.NaN; 
     } 

     if (Validation.GetHasError(textBox)) 
     { 
     this.SetTextBoxMargin(TEXTBOX_MARGIN_RIGHT, textBox); 
     } 

     return textBox.Width; 
    } 

    private void SetTextBoxMargin(double marginRight, TextBox textBox) 
    { 
     if (textBox.Tag == null) 
     { 
     textBox.TextChanged += new TextChangedEventHandler(this.TextBoxTextChanged); 

     textBox.Unloaded += new RoutedEventHandler(this.TextBoxUnloaded); 

     double right = textBox.Margin.Right + marginRight; 

     textBox.Tag = textBox.Margin.Right; 

     textBox.Margin = new Thickness(textBox.Margin.Left, textBox.Margin.Top, right, textBox.Margin.Bottom); 
     } 
    } 

    private void TextBoxUnloaded(object sender, RoutedEventArgs e) 
    { 
     TextBox textBox = sender as TextBox; 

     if (textBox == null) 
     { 
     return; 
     } 

     textBox.TextChanged -= new TextChangedEventHandler(this.TextBoxTextChanged); 

     textBox.Unloaded -= new RoutedEventHandler(this.TextBoxUnloaded); 
    } 

    private void TextBoxTextChanged(object sender, TextChangedEventArgs e) 
    { 
     TextBox textBox = sender as TextBox; 

     if (textBox == null) 
     { 
     return; 
     } 

     if (Validation.GetHasError(textBox)) 
     { 
     this.SetTextBoxMargin(TEXTBOX_MARGIN_RIGHT, textBox); 

     return; 
     } 

     if (textBox.Tag != null) 
     { 
     double tag; 

     double.TryParse(textBox.Tag.ToString(), out tag); 

     textBox.Tag = null; 

     textBox.Margin = new Thickness(textBox.Margin.Left, textBox.Margin.Top, tag, textBox.Margin.Bottom); 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

在你Validation.ErrorTemplate,转换器适用于Validation.HasError触发:

<Style.Triggers> 
    <Trigger Property="Validation.HasError" Value="true"> 
    <Setter Property="Width" Value="{Binding Converter={StaticResource TextBoxMarginConverter}, RelativeSource={RelativeSource Self}}"/> 
    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}"/> 
    </Trigger> 
</Style.Triggers>