编辑:好吧,我不确定这是最好的解决方案(我当然希望有人能提供更好的解决方案),但这里是:
您可以添加一些文本块并将它们绑定到Validation.HasError和(Validation.Errors)[0].ErrorContent,而不是使用Validation.ErrorTeplate(它将显示AdornerLayer中的所有视觉效果),使用客户IValueConverter将Validation.HasError bool转换为可见性值。它看起来类似于以下内容:
Window1.cs:
<Window x:Class="WpfApplicationTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:WpfApplicationTest"
Title="Window1" Height="300" Width="300">
<Grid Margin="10">
<Grid.Resources>
<!-- The person we are binding to -->
<local:Person x:Key="charles" Name="Charles" Age="20" />
<!-- The convert to use-->
<local:HasErrorToVisibilityConverter x:Key="visibilityConverter" />
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- The name -->
<TextBox Name="NameTextBox" Grid.Row="0" Text="{Binding Source={StaticResource charles}, Path=Name, ValidatesOnDataErrors=true}" />
<TextBlock Grid.Row="1"
Foreground="Red"
Text="{Binding ElementName=NameTextBox, Path=(Validation.Errors)[0].ErrorContent}"
Visibility="{Binding ElementName=NameTextBox, Path=(Validation.HasError), Converter={StaticResource visibilityConverter}}" />
<!-- The age -->
<TextBox Name="AgeTextBox" Grid.Row="2" Text="{Binding Source={StaticResource charles}, Path=Age, ValidatesOnExceptions=true}" />
<TextBlock Grid.Row="3"
Foreground="Red"
Text="{Binding ElementName=AgeTextBox, Path=(Validation.Errors)[0].ErrorContent}"
Visibility="{Binding ElementName=AgeTextBox, Path=(Validation.HasError), Converter={StaticResource visibilityConverter}}" />
</Grid>
</Window>
Person.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Text.RegularExpressions;
namespace WpfApplicationTest
{
public class Person : IDataErrorInfo
{
public string Name { get; set; }
public int Age { get; set; }
#region IDataErrorInfo Members
string IDataErrorInfo.Error
{
get { throw new NotImplementedException(); }
}
string IDataErrorInfo.this[string columnName]
{
get
{
switch (columnName)
{
case ("Name"):
if (Regex.IsMatch(this.Name, "[^a-zA-Z ]"))
{
return "Name may contain only letters and spaces.";
}
else
{
return null;
}
default:
return null;
}
}
}
#endregion
}
}
HasErrorToVisibilityConverter.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Windows;
namespace WpfApplicationTest
{
[ValueConversion(typeof(bool), typeof(Visibility))]
public class HasErrorToVisibilityConverter : IValueConverter
{
#region IValueConverter Members
object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool hasError = (bool)value;
return hasError ? Visibility.Visible : Visibility.Collapsed;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
}
它的可伸缩性不如拥有一个可以在所有控件中引用的控件模板,但这是我找到的唯一解决方案。我感觉到了你的痛苦——我能找到的关于WPF验证的每个例子都非常简单,而且几乎总是使用“!”或控件前面的“*”,工具提示绑定到(Validation.Errors)[0]。ErrorContent。。。
祝你好运!如果我找到更好的解决方案,我将更新此;)