您的位置:首页 > 其它

WPF前台数据验证(红框)Validation.ErrorTemplate 附加属性

2013-02-18 18:30 441 查看
WPF 显示验证错误的默认方式是在控件周围绘制红色边框。通常需要对此方法进行自定义,以通过其他方式来显示错误。而且,默认情况下不会显示与验证错误关联的错误消息。常见的要求是仅当存在验证错误时才在工具提示中显示错误消息。通过将
Styles 和一组与验证关联的附加属性进行组合,可以相当轻松地自定义验证错误显示。



前台xaml:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<!-- 应该在此定义资源字典条目。-->
<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">
<GradientStop Color="#ABADB3" Offset="0.05"/>
<GradientStop Color="#E2E3EA" Offset="0.07"/>
<GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<ControlTemplate x:Key="validationTemplate">

</ControlTemplate>
<Style BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource validationTemplate}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid x:Name="root">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1"/>
</Grid.ColumnDefinitions>
<!--<Border x:Name="Border" Background="White" BorderBrush="Gray" BorderThickness="0" Padding="2" CornerRadius="1">-->
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Microsoft_Windows_Themes:ListBoxChrome>
<!--</Border>-->
<Border x:Name="border"  BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1" Visibility="Collapsed"  HorizontalAlignment="Stretch" Margin="0" Width="Auto">

<Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">
<Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="#FFDC000C" Margin="1,3,0,0"/>
<Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff" Margin="1,3,0,0"/>
</Grid>
</Border>
<Popup x:Name="popup" Placement="Right" IsOpen="False">
<Border x:Name="border1_Copy" Width="Auto" Height="Auto" Background="Red" BorderThickness="0" >
<TextBlock TextWrapping="NoWrap" Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/>
</Border>
<!--<Grid Width="50" Height="20" Background="Red"/>-->

</Popup>
<!--<Popup x:Name="popup"  Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"  Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top" IsOpen="False" StaysOpen="True" AllowsTransparency="True">
<Border x:Name="border1_Copy" BorderThickness="1" Margin="0" Background="Red" CornerRadius="2"  HorizontalAlignment="Stretch" Opacity="0" RenderTransformOrigin="0.5,0.5" Height="Auto" Width="Auto">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform X="10"/>
</TransformGroup>
</Border.RenderTransform>
<Border.Effect>
<DropShadowEffect Direction="-90" BlurRadius="5" Color="#FF808080" ShadowDepth="1"/>
</Border.Effect>
<TextBlock TextWrapping="NoWrap" Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/>
</Border>
</Popup>-->
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Visibility" TargetName="border" Value="Visible"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Validation.HasError" Value="True"/>
<Condition Property="IsFocused" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="IsOpen" TargetName="popup" Value="True"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--<Style TargetType="TextBox">
<Style.Triggers>

<Trigger Property="Validation.HasError"
Value="True">

<Setter Property="ToolTip">

<Setter.Value>

<Binding Path="(Validation.Errors).CurrentItem.ErrorContent" RelativeSource="{x:Static RelativeSource.Self}" />

</Setter.Value>

</Setter>

</Trigger>

</Style.Triggers>

</Style>-->
</ResourceDictionary>


后台代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication11111
{
/// <summary>
/// UserControl2.xaml 的交互逻辑
/// </summary>
public partial class UserControl2 : UserControl
{
private UserInfo _UserInfo;
public UserControl2()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(UserControl2_Loaded);
}

void UserControl2_Loaded(object sender, RoutedEventArgs e)
{
_UserInfo = new UserInfo();
this.DataContext = _UserInfo;
}

private void btnSave_Click(object sender, RoutedEventArgs e)
{
//txtName.Visibility = Visibility.Collapsed;
UserControl1 _UserControl1 = new UserControl1();
grid.Children.Add(_UserControl1);
string _name = _UserInfo.Name;
string _pass = _UserInfo.Pass;
}
}
}


实体类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace WpfApplication11111
{
public class UserInfo : ValidationUtility, INotifyPropertyChanged
{
#region 数据更新通知

public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChange(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

#endregion

private string _Name;

[Required(ErrorMessage = "[登录名]内容不能为空!")]
[StringLength(255, ErrorMessage = "[登录名]内容最大允许255个字符!")]
[RegularExpression("^[A-Za-z0-9]+$", ErrorMessage = "[登录名]格式不正确!")]
/// <summary>
///
/// </summary>
public string Name
{
get { return _Name; }
set
{
//Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Name" });
//if (string.IsNullOrEmpty(value))
//{
//    throw new Exception("用户名不能为空.");
//}
_Name = value;
NotifyPropertyChange("Name");
}
}

private string _Pass;
[Required(ErrorMessage = "[密码]内容不能为空!")]
[StringLength(255, ErrorMessage = "[密码]内容最大允许255个字符!")]
[RegularExpression("^[A-Za-z0-9]+$", ErrorMessage = "[密码]格式不正确!")]
/// <summary>
///
/// </summary>
public string Pass
{
get { return _Pass; }
set
{
//if (string.IsNullOrEmpty(value))
//{
//    throw new Exception("密码不能为空.");
//}
_Pass = value;
NotifyPropertyChange("Pass");
}
}

}
}


ValidationUtility.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using System.ComponentModel.DataAnnotations;

namespace WpfApplication11111
{
public class ValidationUtility : IDataErrorInfo
{
public string Error
{
get { return _error; }
}

public string _error;

public string this[string columnName]
{
get
{
Type tp = this.GetType();
PropertyInfo pi = tp.GetProperty(columnName);
var value = pi.GetValue(this, null);
object[] Attributes = pi.GetCustomAttributes(false);
if (Attributes != null && Attributes.Length > 0)
{
foreach (object attribute in Attributes)
{
if (attribute is ValidationAttribute)
{
ValidationAttribute vAttribute = attribute as ValidationAttribute;
if (!vAttribute.IsValid(value))
{
_error = vAttribute.ErrorMessage;
return _error;
}
}
}
}
return null;
}
}
}
}

追加PasswordBox验证

<Style TargetType="{x:Type PasswordBox}">
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource validationTemplate}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<Setter Property="FontFamily" Value="Times New Roman"/>
<Setter Property="PasswordChar" Value="●"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Grid x:Name="root">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1"/>
</Grid.ColumnDefinitions>
<!--<Border x:Name="Border" Background="White" BorderBrush="Gray" BorderThickness="0" Padding="2" CornerRadius="1">-->
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Microsoft_Windows_Themes:ListBoxChrome>
<!--</Border>-->
<Border x:Name="border"  BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1" Visibility="Collapsed"  HorizontalAlignment="Stretch" Margin="0" Width="Auto">

<Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">
<Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="#FFDC000C" Margin="1,3,0,0"/>
<Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff" Margin="1,3,0,0"/>
</Grid>
</Border>
<Popup x:Name="popup" Placement="Right" IsOpen="False">
<Border x:Name="border1_Copy" Width="Auto" Height="Auto" Background="Red" BorderThickness="0" >
<TextBlock TextWrapping="NoWrap" Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/>
</Border>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Visibility" TargetName="border" Value="Visible"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Validation.HasError" Value="True"/>
<Condition Property="IsFocused" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="IsOpen" TargetName="popup" Value="True"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


代码下载地址:

http://download.csdn.net/detail/hwt0101/5070730

相关地址:

http://msdn.microsoft.com/zh-cn/magazine/ff714593.aspx

http://msdn.microsoft.com/zh-cn/library/system.windows.controls.validation.errortemplate(v=vs.90).aspx
http://msdn.microsoft.com/en-us/library/ms752068(v=vs.100).aspx
http://wpf.codeplex.com/releases/view/14962
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: