加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

WPF 输入控件 验证操作和样式模板经典样式分享

(2013-11-06 15:31:28)
标签:

wpf

验证

validation

it

分类: 实用操作研究

输入控件往往需要验证的,通常在表单中尤为如此。wpf的验证机制相较silverlight的稍微复杂。但操作起来还行。本篇由浅入深(其实也没有很深)介绍下wpf的验证使用 并 分享几个实用的 验证样式。

 

先上一个比较简单的例子,来看下wpf默认情况下验证时的样子:

前台:

<</FONT>TextBox x:Name="tb_Num" Width="120" VerticalAlignment="Center">

<</FONT>TextBox.Text>

<</FONT>Binding Path="Age" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">

<</FONT>Binding.ValidationRules>

<</FONT>ExceptionValidationRule/>

</</FONT>Binding.ValidationRules>

</</FONT>Binding>

</</FONT>TextBox.Text>

</</FONT>TextBox>

实体类:

public class Person

{

public int Age { get; set; }

}

后台赋值:

tb_Num.DataContext = new Person();

看下效果:

默认情况下

http://s11/mw690/002kMojxty6E0DVmFpEda&690输入控件 验证操作和样式模板经典样式分享" TITLE="WPF 输入控件 验证操作和样式模板经典样式分享" />
输入值为空
http://s10/mw690/002kMojxty6E0DVookN59&690输入控件 验证操作和样式模板经典样式分享" TITLE="WPF 输入控件 验证操作和样式模板经典样式分享" />
输入值为字母
http://s8/mw690/002kMojxty6E0DVq3lR37&690输入控件 验证操作和样式模板经典样式分享" TITLE="WPF 输入控件 验证操作和样式模板经典样式分享" />
输入值大于Int范围
http://s4/mw690/002kMojxty6E0DVsl1h73&690输入控件 验证操作和样式模板经典样式分享" TITLE="WPF 输入控件 验证操作和样式模板经典样式分享" />
可以看到,当不符合输入规则时,输入框会变红。但没有任何输入出错提示,这点跟silverlight就不一样。

上面例子中用到的方法是 ValidationRules 是wpf验证方案中最常用两种方法的一个,另一个方法是继承

IDataErrorInfo。下面的例子具体给出了这两种方法的具体使用。

 

方法一:使用ValidationRules

第一个例子中使用的是默认的ExceptionValidationRule,但更普遍的情况下是使用自己定义的验证规则哟!~

后台定义的自定义规则

public class RequiredRule : ValidationRule

{

private int minmunLength = -1;

private int maxmunLength = -1;

private string errorMessage;

public int MinmunLength

{

get { return minmunLength; }

set { minmunLength = value; }

}

public int MaxmunLength

{

get { return maxmunLength; }

set { maxmunLength = value; }

}

public string ErrorMessage

{

get { return errorMessage; }

set { errorMessage = value; }

}

public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)

{

ValidationResult result = new ValidationResult(true, null);

if (value == null)

result = new ValidationResult(false, "不能为空值!");

if (string.IsNullOrEmpty(value.ToString()))

result = new ValidationResult(false, "不能为空字符串");

string inputstring = (value ?? string.Empty).ToString();

if (inputstring.Length < this.minmunLength || (this.maxmunLength > 0 && inputstring.Length > this.maxmunLength))

result = new ValidationResult(false, this.errorMessage);

return result;

}

}

前台:

<</FONT>TextBox x:Name="textbox" Width="120" VerticalAlignment="Center" >

<</FONT>TextBox.Text >

<</FONT>Binding Path="Name" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">

<</FONT>Binding.ValidationRules>

<</FONT>local:RequiredRule MinmunLength="0" MaxmunLength="10" ErrorMessage="字符串最多10个字符!"/>

</</FONT>Binding.ValidationRules>

</</FONT>Binding>

</</FONT>TextBox.Text>

</</FONT>TextBox>

后台数据绑定和实体类:

textbox.DataContext = new Person();

public class Person

{

public string Name { get; set; }

}

然后为了在输入出错时,有相应内容的显示,我们是要设置TextBox的样式的。

<</FONT>ControlTemplate x:Key="ErrorTemplate">

<</FONT>Border BorderBrush="Red" BorderThickness="1">

<</FONT>AdornedElementPlaceholder/>

</</FONT>Border>

</</FONT>ControlTemplate>

<</FONT>Style TargetType="TextBox">

<</FONT>Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate}"></</FONT>Setter>

<</FONT>Style.Triggers>

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

<</FONT>Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},Path=(Validation.Errors)[0].ErrorContent}"/>

</</FONT>Trigger>

</</FONT>Style.Triggers>

</</FONT>Style>

主要需要编辑的是Validation.ErrorTemplate,那个Validation.HasError = true 时主要触发ToolTip 的显示

效果就是带有tooltip的出错提示!~

 

方法二:使用IDataErrorInfo

前台代码中去掉

<</FONT>Binding.ValidationRules>

<</FONT>local:RequiredRule MinmunLength="0" MaxmunLength="10" ErrorMessage="字符串最多10个字符!"/>

</</FONT>Binding.ValidationRules>

后台实体类改造:

public class BaseDataErrorInfo : IDataErrorInfo

{

private string _error;

public string this[string columnName]

{

get { return GetErrorFor(columnName); }

}

public string Error

{

get { return _error; }

set { _error = value; }

}

public virtual string GetErrorFor(string columnName)

{

return string.Empty;

}

}

public class Person : BaseDataErrorInfo

{

public string Name { get; set; }

public override string GetErrorFor(string columnName)

{

if (columnName == "Name")

if (string.IsNullOrEmpty(Name))

return "Name 不能为空";

return base.GetErrorFor(columnName);

}

}

效果等同于用第一种方法,不过,在页面Loaded的时候,就开始进行验证了。

 

两种方法都说明完毕了,下面提供几种 Validation.ErrorTemplate 的样式。

http://s1/mw690/002kMojxty6E0IXri0wc0&690输入控件 验证操作和样式模板经典样式分享" TITLE="WPF 输入控件 验证操作和样式模板经典样式分享" />

样式代码:

<</FONT>ControlTemplate x:Key="InputErrorTemplate">

<</FONT>DockPanel>

<</FONT>Ellipse DockPanel.Dock="Right" Margin="2,0" ToolTip="Contains invalid data" Width="10" Height="10">

<</FONT>Ellipse.Fill>

<</FONT>LinearGradientBrush>

<</FONT>GradientStop Color="#11FF1111" Offset="0" />

<</FONT>GradientStop Color="#FFFF0000" Offset="1" />

</</FONT>LinearGradientBrush>

</</FONT>Ellipse.Fill>

</</FONT>Ellipse>

<</FONT>AdornedElementPlaceholder />

</</FONT>DockPanel>

</</FONT>ControlTemplate>

http://s12/mw690/002kMojxty6E0J3MWQXcb&690输入控件 验证操作和样式模板经典样式分享" TITLE="WPF 输入控件 验证操作和样式模板经典样式分享" />
样式代码:

<</FONT>ControlTemplate x:Key="validationTemplate">

<</FONT>DockPanel LastChildFill="True">

<</FONT>TextBlock DockPanel.Dock="Bottom" Foreground="Red" FontWeight="Bold"

Text="{Binding ElementName=Adorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"/>

<</FONT>Border BorderBrush="Red" BorderThickness="1">

<</FONT>AdornedElementPlaceholder x:Name="Adorner"/>

</</FONT>Border>

</</FONT>DockPanel>

</</FONT>ControlTemplate>

http://s6/mw690/002kMojxty6E0Jaos97e5&690输入控件 验证操作和样式模板经典样式分享" TITLE="WPF 输入控件 验证操作和样式模板经典样式分享" />
样式代码:(这个带动画效果的哟!~)

<</FONT>ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.Visibility)">

<</FONT>DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Hidden}"/>

<</FONT>DiscreteObjectKeyFrame KeyTime="00:00:00.2000000" Value="{x:Static Visibility.Visible}"/>

<</FONT>DiscreteObjectKeyFrame KeyTime="00:00:00.4000000" Value="{x:Static Visibility.Hidden}"/>

<</FONT>DiscreteObjectKeyFrame KeyTime="00:00:00.6000000" Value="{x:Static Visibility.Visible}"/>

<</FONT>DiscreteObjectKeyFrame KeyTime="00:00:00.8000000" Value="{x:Static Visibility.Hidden}"/>

<</FONT>DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static Visibility.Visible}"/>

</</FONT>ObjectAnimationUsingKeyFrames>

</</FONT>Storyboard>

<</FONT>ControlTemplate x:Key="ImplicateTemplate">

<</FONT>DockPanel LastChildFill="True">

<</FONT>Ellipse DockPanel.Dock="Right" ToolTip="{Binding ElementName=myTextbox, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"

Width="15" Height="15" Margin="-25,0,0,0" StrokeThickness="1" Fill="Red" >

<</FONT>Ellipse.Stroke>

<</FONT>LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">

<</FONT>GradientStop Color="#FFFA0404" Offset="0"/>

<</FONT>GradientStop Color="#FFC9C7C7" Offset="1"/>

</</FONT>LinearGradientBrush>

</</FONT>Ellipse.Stroke>

<</FONT>Ellipse.Triggers>

<</FONT>EventTrigger RoutedEvent="FrameworkElement.Loaded">

<</FONT>BeginStoryboard Storyboard="{StaticResource FlashErrorIcon}"/>

</</FONT>EventTrigger>

</</FONT>Ellipse.Triggers>

</</FONT>Ellipse>

<</FONT>TextBlock DockPanel.Dock="Right" ToolTip="{Binding ElementName=myControl,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"

Foreground="White" FontSize="11pt" Margin="-15,5,0,0" FontWeight="Bold">!

<</FONT>TextBlock.Triggers>

<</FONT>EventTrigger RoutedEvent="FrameworkElement.Loaded">

<</FONT>BeginStoryboard Storyboard="{StaticResource FlashErrorIcon}"/>

</</FONT>EventTrigger>

</</FONT>TextBlock.Triggers>

</</FONT>TextBlock>

<</FONT>Border BorderBrush="Red" BorderThickness="1">

<</FONT>AdornedElementPlaceholder Name="myControl"/>

</</FONT>Border>

</</FONT>DockPanel>

</</FONT>ControlTemplate>

http://s11/mw690/002kMojxty6E0Jjem5sca&690输入控件 验证操作和样式模板经典样式分享" TITLE="WPF 输入控件 验证操作和样式模板经典样式分享" />

样式代码:(这个是效仿Silverlight的验证效果来的,有动画效果,体验很是不错)

<</FONT>local:BooleanOrConverter x:Key="BooleanOrConverter"/>

<</FONT>ControlTemplate x:Key="errorTemplateSilverlightStyle">

<</FONT>StackPanel Orientation="Horizontal">

<</FONT>Border BorderThickness="1" BorderBrush="#FFdc000c" CornerRadius="0.7" VerticalAlignment="Top">

<</FONT>Grid>

<</FONT>Polygon x:Name="toolTipCorner" Grid.ZIndex="2" Margin="-1" Points="6,6 6,0 0,0" Fill="#FFdc000c" HorizontalAlignment="Right" VerticalAlignment="Top" IsHitTestVisible="True"/>

<</FONT>Polyline Grid.ZIndex="3" Points="7,7 0,0" Margin="-1" HorizontalAlignment="Right" StrokeThickness="1.5" StrokeEndLineCap="Round" StrokeStartLineCap="Round" Stroke="White" VerticalAlignment="Top" IsHitTestVisible="True"/>

<</FONT>AdornedElementPlaceholder x:Name="adorner"/>

</</FONT>Grid>

</</FONT>Border>

<</FONT>Border x:Name="errorBorder" Background="#FFdc000c" Margin="1,0,0,0" Opacity="0" CornerRadius="1.5" IsHitTestVisible="False" MinHeight="24" MaxWidth="267">

<</FONT>Border.Effect>

<</FONT>DropShadowEffect ShadowDepth="2.25" Color="Black" Opacity="0.4" Direction="315" BlurRadius="4"/>

</</FONT>Border.Effect>

<</FONT>TextBlock Text="{Binding ElementName=adorner,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" Foreground="White" Margin="8,3,8,3" TextWrapping="Wrap"/>

</</FONT>Border>

</</FONT>StackPanel>

<</FONT>ControlTemplate.Triggers>

<</FONT>DataTrigger Value="True">

<</FONT>DataTrigger.Binding>

<</FONT>MultiBinding Converter="{StaticResource BooleanOrConverter}">

<</FONT>Binding ElementName="adorner" Path="AdornedElement.IsKeyboardFocused" />

<</FONT>Binding ElementName="toolTipCorner" Path="IsMouseOver"/>

</</FONT>MultiBinding>

</</FONT>DataTrigger.Binding>

<</FONT>DataTrigger.EnterActions>

<</FONT>BeginStoryboard x:Name="fadeInStoryboard">

<</FONT>Storyboard>

<</FONT>DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="errorBorder" Storyboard.TargetProperty="Opacity" To="1"/>

<</FONT>ThicknessAnimation Duration="00:00:00.15" Storyboard.TargetName="errorBorder" Storyboard.TargetProperty="Margin" FillBehavior="HoldEnd" From="1,0,0,0" To="5,0,0,0">

<</FONT>ThicknessAnimation.EasingFunction>

<</FONT>BackEase EasingMode="EaseOut" Amplitude="2"/>

</</FONT>ThicknessAnimation.EasingFunction>

</</FONT>ThicknessAnimation>

</</FONT>Storyboard>

</</FONT>BeginStoryboard>

</</FONT>DataTrigger.EnterActions>

<</FONT>DataTrigger.ExitActions>

<</FONT>StopStoryboard BeginStoryboardName="fadeInStoryboard"/>

<</FONT>BeginStoryboard x:Name="fadeOutStoryBoard">

<</FONT>Storyboard>

<</FONT>DoubleAnimation Duration="00:00:00" Storyboard.TargetName="errorBorder" Storyboard.TargetProperty="Opacity" To="0"/>

</</FONT>Storyboard>

</</FONT>BeginStoryboard>

</</FONT>DataTrigger.ExitActions>

</</FONT>DataTrigger>

</</FONT>ControlTemplate.Triggers>

</</FONT>ControlTemplate>

后台用了一个Converter,用来设置触发验证

public class BooleanOrConverter : IMultiValueConverter

{

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{

foreach (object value in values)

{

if ((bool)value == true)

{

return true;

}

}

return false;

}

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)

{

throw new NotSupportedException();

}

}

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有