WPF Validation.has设置文本框上的边距时出错

WPF Validation.has设置文本框上的边距时出错,wpf,validation,templates,Wpf,Validation,Templates,我一直在想方设法解决这个问题( 对于文本框,我有一个Validation.ErrorTemplate设置,当文本框出现验证错误时,文本框右侧有一个图像 这很好!但我想做的一件事是调整文本框的大小或设置有错误的边距,使其适合文本框在表单上的空间。目前,图像在文本框区域之外流动 我真正想要的是有错误的文本框与没有错误的文本框占用相同的空间 以下是我的XAML风格: <Style TargetType="{x:Type TextBox}"> <Style.Resources>

我一直在想方设法解决这个问题(

对于文本框,我有一个Validation.ErrorTemplate设置,当文本框出现验证错误时,文本框右侧有一个图像

这很好!但我想做的一件事是调整文本框的大小或设置有错误的边距,使其适合文本框在表单上的空间。目前,图像在文本框区域之外流动

我真正想要的是有错误的文本框与没有错误的文本框占用相同的空间

以下是我的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查看是否能看到属性被触摸或更改,但什么都没有发生

页边距是Validation.HasError属性无法更改的属性吗

任何洞察都会很棒


谢谢!

希望能帮助任何可能遇到此问题的人

我仍然不确定Validation.HasError触发器期间为什么边距属性没有更改,但我发现了一个棘手的问题

该解决方法使用IValueConverter设置边距,利用一些事件(TextChanged和卸载以清除事件)劫持Width属性绑定。我使用TextBox标记属性保留原始边距,在我的情况下,我只担心正确的边距

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>