我有一个使用验证的WPF窗口.我创建了一个错误模板,在一个未通过验证的元素周围放置一个红色边框,并在下面显示错误消息.这工作正常,但错误消息在控件下面的任何控件上呈现,并带有错误.我能说的最好,发生这种情况是因为错误模板在Adorner Layer上呈现,而Adorner Layer位于其他所有层之上.我希望发生的是其他一切都向下移动以便为错误消息腾出空间.有没有办法做到这一点?网络上的所有示例似乎都使用工具提示,并使用一个简单的指标,如星号或感叹号,不占用太多空间.
这是模板:
<ControlTemplate x:Key="ValidationErrorTemplate">
<StackPanel>
<Border BorderBrush="Red" BorderThickness="2" CornerRadius="2">
<AdornedElementPlaceholder x:Name="placeholder"/>
</Border>
<TextBlock Foreground="Red" FontSize="10" Text="{Binding ElementName=placeholder, Path=AdornedElement.(Validation.Errors)[0].ErrorContent, FallbackValue=Error!}"></TextBlock>
</StackPanel>
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)
以下是使用模板的控件(我输入了一些,所以忽略任何语法错误):
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Name="Account" Grid.Row="0" Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}" Width="200">
<TextBox.Text>
<Binding Path="AccountNumber">
<Binding.ValidationRules>
<validators:RequiredValueValidationRule/>
<validators:NumericValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBox Name="Expiration" Grid.Row="1" Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}" Width="100" Margin="0,2,5,2">
<TextBox.Text>
<Binding Path="ExpirationDate">
<Binding.ValidationRules>
<validators:ExpirationDateValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
Run Code Online (Sandbox Code Playgroud)
编辑:好吧,我不肯定这是最好的解决方案(我当然希望有人可以提供更好的解决方案),但这里有:
您可以添加一些TextBlock并将它们绑定到Validation.HasError和(Validation.Errors)[0] .ErrorContent,使用客户IValueConverter转换,而不是使用Validation.ErrorTeplate(它将显示AdornerLayer中的所有视觉效果). Validation.HasError bool到Visibility值.它看起来像下面这样:
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>
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
它没有扩展,只有你可以在所有控件中引用的单个ControlTemplate,但它是我找到的唯一解决方案.我感觉到你的痛苦 - 几乎每个关于WPF验证主题的例子都非常简单,而且几乎总是使用'!' 或者'*'在控件之前,工具提示绑定到(Validation.Errors)[0] .ErrorContent ...
祝你好运!如果我找到更好的解决方案,我会更新这个;)
| 归档时间: |
|
| 查看次数: |
2365 次 |
| 最近记录: |