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

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值