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

前台xaml:

  1. <ResourceDictionary
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
  4. <!-- 应该在此定义资源字典条目。-->
  5. <LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">
  6. <GradientStop Color="#ABADB3" Offset="0.05"/>
  7. <GradientStop Color="#E2E3EA" Offset="0.07"/>
  8. <GradientStop Color="#E3E9EF" Offset="1"/>
  9. </LinearGradientBrush>
  10. <ControlTemplate x:Key="validationTemplate">
  11. </ControlTemplate>
  12. <Style BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
  13. <Setter Property="Validation.ErrorTemplate" Value="{StaticResource validationTemplate}" />
  14. <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
  15. <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
  16. <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
  17. <Setter Property="BorderThickness" Value="1"/>
  18. <Setter Property="Padding" Value="1"/>
  19. <Setter Property="AllowDrop" Value="true"/>
  20. <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
  21. <Setter Property="Template">
  22. <Setter.Value>
  23. <ControlTemplate TargetType="{x:Type TextBox}">
  24. <Grid x:Name="root">
  25. <Grid.ColumnDefinitions>
  26. <ColumnDefinition Width="*"/>
  27. <ColumnDefinition Width="1"/>
  28. </Grid.ColumnDefinitions>
  29. <!--<Border x:Name="Border" Background="White" BorderBrush="Gray" BorderThickness="0" Padding="2" CornerRadius="1">-->
  30. <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
  31. <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
  32. </Microsoft_Windows_Themes:ListBoxChrome>
  33. <!--</Border>-->
  34. <Border x:Name="border"  BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1" Visibility="Collapsed"  HorizontalAlignment="Stretch" Margin="0" Width="Auto">
  35. <Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">
  36. <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"/>
  37. <Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff" Margin="1,3,0,0"/>
  38. </Grid>
  39. </Border>
  40. <Popup x:Name="popup" Placement="Right" IsOpen="False">
  41. <Border x:Name="border1_Copy" Width="Auto" Height="Auto" Background="Red" BorderThickness="0" >
  42. <TextBlock TextWrapping="NoWrap" Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/>
  43. </Border>
  44. <!--<Grid Width="50" Height="20" Background="Red"/>-->
  45. </Popup>
  46. <!--<Popup x:Name="popup"  Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"  Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top" IsOpen="False" StaysOpen="True" AllowsTransparency="True">
  47. <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">
  48. <Border.RenderTransform>
  49. <TransformGroup>
  50. <ScaleTransform/>
  51. <SkewTransform/>
  52. <RotateTransform/>
  53. <TranslateTransform X="10"/>
  54. </TransformGroup>
  55. </Border.RenderTransform>
  56. <Border.Effect>
  57. <DropShadowEffect Direction="-90" BlurRadius="5" Color="#FF808080" ShadowDepth="1"/>
  58. </Border.Effect>
  59. <TextBlock TextWrapping="NoWrap" Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/>
  60. </Border>
  61. </Popup>-->
  62. </Grid>
  63. <ControlTemplate.Triggers>
  64. <Trigger Property="Validation.HasError" Value="True">
  65. <Setter Property="Visibility" TargetName="border" Value="Visible"/>
  66. </Trigger>
  67. <MultiTrigger>
  68. <MultiTrigger.Conditions>
  69. <Condition Property="Validation.HasError" Value="True"/>
  70. <Condition Property="IsFocused" Value="True"/>
  71. </MultiTrigger.Conditions>
  72. <Setter Property="IsOpen" TargetName="popup" Value="True"/>
  73. </MultiTrigger>
  74. </ControlTemplate.Triggers>
  75. </ControlTemplate>
  76. </Setter.Value>
  77. </Setter>
  78. </Style>
  79. <!--<Style TargetType="TextBox">
  80. <Style.Triggers>
  81. <Trigger Property="Validation.HasError"
  82. Value="True">
  83. <Setter Property="ToolTip">
  84. <Setter.Value>
  85. <Binding Path="(Validation.Errors).CurrentItem.ErrorContent" RelativeSource="{x:Static RelativeSource.Self}" />
  86. </Setter.Value>
  87. </Setter>
  88. </Trigger>
  89. </Style.Triggers>
  90. </Style>-->
  91. </ResourceDictionary>

后台代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Data;
  8. using System.Windows.Documents;
  9. using System.Windows.Input;
  10. using System.Windows.Media;
  11. using System.Windows.Media.Imaging;
  12. using System.Windows.Navigation;
  13. using System.Windows.Shapes;
  14. namespace WpfApplication11111
  15. {
  16. /// <summary>
  17. /// UserControl2.xaml 的交互逻辑
  18. /// </summary>
  19. public partial class UserControl2 : UserControl
  20. {
  21. private UserInfo _UserInfo;
  22. public UserControl2()
  23. {
  24. InitializeComponent();
  25. this.Loaded += new RoutedEventHandler(UserControl2_Loaded);
  26. }
  27. void UserControl2_Loaded(object sender, RoutedEventArgs e)
  28. {
  29. _UserInfo = new UserInfo();
  30. this.DataContext = _UserInfo;
  31. }
  32. private void btnSave_Click(object sender, RoutedEventArgs e)
  33. {
  34. //txtName.Visibility = Visibility.Collapsed;
  35. UserControl1 _UserControl1 = new UserControl1();
  36. grid.Children.Add(_UserControl1);
  37. string _name = _UserInfo.Name;
  38. string _pass = _UserInfo.Pass;
  39. }
  40. }
  41. }

实体类:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.ComponentModel;
  6. using System.ComponentModel.DataAnnotations;
  7. namespace WpfApplication11111
  8. {
  9. public class UserInfo : ValidationUtility, INotifyPropertyChanged
  10. {
  11. #region 数据更新通知
  12. public event PropertyChangedEventHandler PropertyChanged;
  13. private void NotifyPropertyChange(string propertyName)
  14. {
  15. if (PropertyChanged != null)
  16. {
  17. PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  18. }
  19. }
  20. #endregion
  21. private string _Name;
  22. [Required(ErrorMessage = "[登录名]内容不能为空!")]
  23. [StringLength(255, ErrorMessage = "[登录名]内容最大允许255个字符!")]
  24. [RegularExpression("^[A-Za-z0-9]+$", ErrorMessage = "[登录名]格式不正确!")]
  25. /// <summary>
  26. ///
  27. /// </summary>
  28. public string Name
  29. {
  30. get { return _Name; }
  31. set
  32. {
  33. //Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Name" });
  34. //if (string.IsNullOrEmpty(value))
  35. //{
  36. //    throw new Exception("用户名不能为空.");
  37. //}
  38. _Name = value;
  39. NotifyPropertyChange("Name");
  40. }
  41. }
  42. private string _Pass;
  43. [Required(ErrorMessage = "[密码]内容不能为空!")]
  44. [StringLength(255, ErrorMessage = "[密码]内容最大允许255个字符!")]
  45. [RegularExpression("^[A-Za-z0-9]+$", ErrorMessage = "[密码]格式不正确!")]
  46. /// <summary>
  47. ///
  48. /// </summary>
  49. public string Pass
  50. {
  51. get { return _Pass; }
  52. set
  53. {
  54. //if (string.IsNullOrEmpty(value))
  55. //{
  56. //    throw new Exception("密码不能为空.");
  57. //}
  58. _Pass = value;
  59. NotifyPropertyChange("Pass");
  60. }
  61. }
  62. }
  63. }

ValidationUtility.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.ComponentModel;
  6. using System.Reflection;
  7. using System.ComponentModel.DataAnnotations;
  8. namespace WpfApplication11111
  9. {
  10. public class ValidationUtility : IDataErrorInfo
  11. {
  12. public string Error
  13. {
  14. get { return _error; }
  15. }
  16. public string _error;
  17. public string this[string columnName]
  18. {
  19. get
  20. {
  21. Type tp = this.GetType();
  22. PropertyInfo pi = tp.GetProperty(columnName);
  23. var value = pi.GetValue(this, null);
  24. object[] Attributes = pi.GetCustomAttributes(false);
  25. if (Attributes != null && Attributes.Length > 0)
  26. {
  27. foreach (object attribute in Attributes)
  28. {
  29. if (attribute is ValidationAttribute)
  30. {
  31. ValidationAttribute vAttribute = attribute as ValidationAttribute;
  32. if (!vAttribute.IsValid(value))
  33. {
  34. _error = vAttribute.ErrorMessage;
  35. return _error;
  36. }
  37. }
  38. }
  39. }
  40. return null;
  41. }
  42. }
  43. }
  44. }

追加PasswordBox验证

    1. <Style TargetType="{x:Type PasswordBox}">
    2. <Setter Property="Validation.ErrorTemplate" Value="{StaticResource validationTemplate}" />
    3. <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    4. <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
    5. <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
    6. <Setter Property="FontFamily" Value="Times New Roman"/>
    7. <Setter Property="PasswordChar" Value="●"/>
    8. <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    9. <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
    10. <Setter Property="BorderThickness" Value="1"/>
    11. <Setter Property="HorizontalContentAlignment" Value="Left"/>
    12. <Setter Property="Padding" Value="1"/>
    13. <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    14. <Setter Property="AllowDrop" Value="true"/>
    15. <Setter Property="Template">
    16. <Setter.Value>
    17. <ControlTemplate TargetType="{x:Type PasswordBox}">
    18. <Grid x:Name="root">
    19. <Grid.ColumnDefinitions>
    20. <ColumnDefinition Width="*"/>
    21. <ColumnDefinition Width="1"/>
    22. </Grid.ColumnDefinitions>
    23. <!--<Border x:Name="Border" Background="White" BorderBrush="Gray" BorderThickness="0" Padding="2" CornerRadius="1">-->
    24. <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
    25. <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
    26. </Microsoft_Windows_Themes:ListBoxChrome>
    27. <!--</Border>-->
    28. <Border x:Name="border"  BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1" Visibility="Collapsed"  HorizontalAlignment="Stretch" Margin="0" Width="Auto">
    29. <Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">
    30. <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"/>
    31. <Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff" Margin="1,3,0,0"/>
    32. </Grid>
    33. </Border>
    34. <Popup x:Name="popup" Placement="Right" IsOpen="False">
    35. <Border x:Name="border1_Copy" Width="Auto" Height="Auto" Background="Red" BorderThickness="0" >
    36. <TextBlock TextWrapping="NoWrap" Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/>
    37. </Border>
    38. </Popup>
    39. </Grid>
    40. <ControlTemplate.Triggers>
    41. <Trigger Property="Validation.HasError" Value="True">
    42. <Setter Property="Visibility" TargetName="border" Value="Visible"/>
    43. </Trigger>
    44. <MultiTrigger>
    45. <MultiTrigger.Conditions>
    46. <Condition Property="Validation.HasError" Value="True"/>
    47. <Condition Property="IsFocused" Value="True"/>
    48. </MultiTrigger.Conditions>
    49. <Setter Property="IsOpen" TargetName="popup" Value="True"/>
    50. </MultiTrigger>
    51. </ControlTemplate.Triggers>
    52. </ControlTemplate>
    53. </Setter.Value>
    54. </Setter>
    55. </Style>
    56. 代码下载地址:

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

WPF前台数据验证(红框)Validation.ErrorTemplate 附加属性的更多相关文章

  1. [WPF] 让第一个数据验证出错(Validation.HasError)的控件自动获得焦点

    1. 需求 在上一篇文章 <在 ViewModel 中让数据验证出错(Validation.HasError)的控件获得焦点>中介绍了如何让 Validation.HasError 的控件 ...

  2. 【WPF】数据验证

    原文:[WPF]数据验证 引言      数据验证在任何用户界面程序中都是不可缺少的一部分.在WPF中,数据验证更是和绑定紧紧联系在一起,下面简单介绍MVVM模式下常用的几种验证方式. 错误信息显示 ...

  3. [WPF 自定义控件]自定义一个“传统”的 Validation.ErrorTemplate

    1. 什么是Validaion.ErrorTemplate 数据绑定模型允许您将与您Binding的对象相关联ValidationRules. 如果用户输入的值无效,你可能希望在应用程序 用户界面 ( ...

  4. [WPF] 在 ViewModel 中让数据验证出错(Validation.HasError)的控件获得焦点

    1. 需求 在 MVVM 中 ViewModel 和 View 之间的交互通常都是靠 Icommand 和 INotifyPropertyChanged,不过有时候还会需要从 MVVM 中控制 Vie ...

  5. 测开之路一百五十五:jquery-validation前台数据验证

    前面做的wtform验证是服务器端的验证,需要把数据传输到服务器,服务器验证后再吧结果传输到前端,网络慢的时候,用户体验不好,所以需要前端验证,且后端验证不能少 传统的js或者jquery如果要验证信 ...

  6. 【Win10】使用 ValidationAttribute 实现数据验证

    WPF 中数据验证的方式多种多样,这里就不说了.但是,在 Windows Phone 8.1 Runtime 中,要实现数据验证,只能靠最基础的手动编写条件判断代码来实现.如果用过 ASP.NET M ...

  7. WPF 中 UserControl作为另一个Process宿主到Window里, ErrorTemplate的默认红框没有出现

    最近做WPF项目遇到一个问题, 我有2个process, 一个Process里只有Usercontrol, 另一个Process获取前一个Process中Usercontrol并host到当前的win ...

  8. WPF数据验证

    当填写表单时,需要对填写的内容进行验证,检查数据是否符合要求,比如字符串的长度.日期的格式.数字等.WPF支持自定义验证规则,并提供可视化反馈,以便在输入无效值时向用户发出通知. 下面的示例将演示一个 ...

  9. WPF中的数据验证

    数据验证 WPF的Binding使得数据能够在数据源和目标之间流通,在数据流通的中间,便能够对数据做一些处理. 数据转换和数据验证便是在数据从源到目标 or 从目标到源 的时候对数据的验证和转换. V ...

随机推荐

  1. C#创建Graphics对象的方法

    方法一.利用控件或窗体的Paint事件中的PainEventArgs 在窗体或控件的Paint事件中接收对图形对象的引用,作为PaintEventArgs(PaintEventArgs指定绘制控件所用 ...

  2. Java程序员最常犯的错误盘点之Top 10

    1. 数组转ArrayList 为了实现把一个数组转换成一个ArrayList,很多Java程序员会使用如下的代码: Arrays.asList确实会返回一个ArrayList对象,但是该类是Arra ...

  3. 10深入理解C指针之---指针运算和比较

    该系列文章源于<深入理解C指针>的阅读与理解,由于本人的见识和知识的欠缺可能有误,还望大家批评指教. 指针运算有很多种,主要有指针的声明*.指针的解引*.指针指向(*).或->.指针 ...

  4. 转载:linux编程,命令行参数输入getopt

    下面资料来自百度百科: getopt(分析命令行参数) 相关函数 表头文件 #include<unistd.h> 定义函数 int getopt(int argc,char * const ...

  5. AC日记——乘积最大 洛谷 P1018

    题目描述 今年是国际数学联盟确定的“2000――世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得 ...

  6. Codeforces Gym101502 A.Very Hard Question

    2017 JUST Programming Contest 3.0 昨天的训练赛,打的好难过,因为被暴打了,写了8题,他们有的写了9题,差了一道dp,博客上写7道题的题解. 因为有一道是套板子过的,并 ...

  7. Codeforces 919 A. Supermarket

    这场cf有点意思,hack场,C题等于1的特判hack很多人(我hack成功3个人,上分了,哈哈哈,咳咳...) D题好像是树形dp,E题好像是中国剩余定理,F题好像还是dp,具体的不清楚,最近dp的 ...

  8. 深入理解vue路由的使用

    vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用.vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来.传统的页面应 ...

  9. 何时才使用https访问项目

    利用keytools生产证书,然后将证书导入到jvm和tomcat中,则访问该项目的时候就以https访问

  10. 微信授权网页登陆,oauth

    1.在微信公众号请求用户网页授权之前.开发人员须要先到公众平台官网中的开发人员中心页配置授权回调域名.请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加http://等协议头. 2.授 ...