WPF-数据验证《十一》

目录

第一部分,IDataErrorInfo

第二部分,ValidationRule


最完美的是最后一个。

在输入数据的时候,数据验证是必不可少的一部分,提高用户的交互性和使用性。

看了很多数据验证的,而且官网的demo也有问题(切换点击的时候,会产生白色的点),本人进行一一整理和对比。

首先验证有3种,本文只说2种,另一种性能比较低,就不说了。

分别是IDataErrorInfo和ValidationRule。

第一部分,IDataErrorInfo

1.建立一个wpf项目

2. Person类代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp2
{
    public class Person : IDataErrorInfo
    {
        private int age;

        public int Age
        {
            get { return age; }
            set { age = value; }
        }

        public string Error
        {
            get
            {
                return null;
            }
        }

        public string this[string name]
        {
            get
            {
                string result = string.Empty;

                if (name == "Age")
                {
                    if (this.age < 0 || this.age > 150)
                    {
                        result = "年龄大于0或者小于150";
                    }
                }
                return result;
            }
        }
    }
}

3.xaml界面

数据源是:

<local:Person x:Key="data"/>

style是:

其中(Validation.Errors)/ErrorContent}可以修改成(Validation.Errors)[0].ErrorContent},都会报错。

        <Style x:Key="textBoxInError" TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip"
                            Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                        Path=(Validation.Errors)/ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>

 整体代码

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:Person x:Key="data"/>
        <Style x:Key="textBoxInError" TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip"
                            Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                        Path=(Validation.Errors)[0].ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <StackPanel Margin="20">
            <TextBlock>输入age:</TextBlock>
            <TextBox Style="{StaticResource textBoxInError}">
                <TextBox.Text>
                    <Binding Path="Age" Source="{StaticResource data}"
                         ValidatesOnExceptions="True"
                         UpdateSourceTrigger="PropertyChanged">
                        <Binding.ValidationRules>
                            <DataErrorValidationRule/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>
            <TextBlock>鼠标悬停查看验证错误消息。</TextBlock>
        </StackPanel>
    </Grid>
</Window>

 4.效果

清空的时候会报错

不要使用这个方法  

第二部分,ValidationRule

ValidationRule验证有3种。

第一种:

1.建立一个程序

2.AgeRangeRule类

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace WpfApp2
{
    public class AgeRangeRule : ValidationRule
    {
        public int Min { get; set; }
        public int Max { get; set; }

        public AgeRangeRule()
        {
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            int age = 0;

            try
            {
                if (((string)value).Length > 0)
                    age = Int32.Parse((String)value);
            }
            catch (Exception e)
            {
                return new ValidationResult(false, $"非法字符或{e.Message}");
            }

            if ((age < Min) || (age > Max))
            {
                return new ValidationResult(false, $"请输入年龄范围: {Min}-{Max}.");
            }
            return ValidationResult.ValidResult;
        }
    }
}

3.实现属性通知的功能,在输入数据的时候,可以进行提示

BindingBase类

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp2
{
    public class BindingBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        //protected virtual void OnPropertyChanged(string propertyName)
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")//此处使用特性
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

4.建立VM,MainViewModel类,继承BindingBase

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp2
{
    public class MainViewModel : BindingBase
    {
        public MainViewModel()
        {

        }

        private string name;

        public string Name
        {
            get { return name; }
            set
            {
                name = value; OnPropertyChanged();//OnPropertyChanged(nameof(name),使用特性,去掉括号的值
            }
        }

        private int number;

        public int Number
        {
            get { return number; }
            set
            {
                number = value; OnPropertyChanged();//OnPropertyChanged(nameof(name),使用特性,去掉括号的值
            }
        }
    }
}

5.xaml界面

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ControlTemplate x:Key="validationTemplate">
            <DockPanel>
                <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
                <AdornedElementPlaceholder/>
            </DockPanel>
        </ControlTemplate>
        <Style x:Key="textBoxInError" TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors)/ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <TextBox Name="textBox1" Width="50" FontSize="15"
         Validation.ErrorTemplate="{StaticResource validationTemplate}"
         Style="{StaticResource textBoxInError}">
            <TextBox.Text>
                <Binding Path="Number" UpdateSourceTrigger="PropertyChanged" >
                    <Binding.ValidationRules>
                        <local:AgeRangeRule Min="21" Max="130"/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
    </Grid>
</Window>

别忘记进行绑定

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 WpfApp2
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainViewModel();
        }
    }
}

6.效果

这个可以使用,切换的瞬间有白色的点。

第二种:

1.建立一个wpf程序

  

2.BindingBase类

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp1
{
    public class BindingBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        //protected virtual void OnPropertyChanged(string propertyName)
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")//此处使用特性
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
 
}

3.建立MV,MainViewModel代码,继承BindingBase,NumberValidationRule是规则,自己可以进行修改

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace WpfApp1
{
    public class MainViewModel : BindingBase
    {
        public MainViewModel()
        {

        }

        private int name;

        public int Name
        {
            get { return name; }
            set
            {
                name = value; OnPropertyChanged();//OnPropertyChanged(nameof(name),使用特性,去掉括号的值
            }
        }

        private string number;

        public string Number
        {
            get { return number; }
            set
            {
                number = value; OnPropertyChanged();//OnPropertyChanged(nameof(name),使用特性,去掉括号的值
            }
        }
    }

    //继承一个ValidationRule,重写Validate方法
    public class NumberValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            double myValue = 0;
            if (double.TryParse(value.ToString(), out myValue))
            {
                if (myValue >= 0 && myValue <= 100)
                {
                    return new ValidationResult(true, null);
                }
            }

            return new ValidationResult(false, "请输入 0 至 100的数字");
        }
    }

}

4.xaml界面,其中资源中是弹框的信息的模板

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ControlTemplate x:Key="validationTemplate">
            <StackPanel Orientation="Horizontal" x:Name="stack">
                <Border>
                    <Grid>
                        <AdornedElementPlaceholder x:Name="adorner"/>
                    </Grid>
                </Border>
                <Popup x:Name="popup" AllowsTransparency="True" Placement="Right" >
                    <Border x:Name="errorBorder" Background="#ffdc000c" Opacity="0" MinHeight="30" >
                        <TextBlock Margin="0" Text="{Binding ElementName=adorner, Path=AdornedElement.(Validation.Errors)/ErrorContent}" Foreground="White" TextWrapping="Wrap" VerticalAlignment="Center"/>
                    </Border>
                </Popup>
            </StackPanel>
            <ControlTemplate.Triggers>
                <DataTrigger Value="True" Binding="{Binding ElementName=adorner,Path=AdornedElement.IsKeyboardFocused}">
                    <DataTrigger.Setters>
                        <Setter Property="IsOpen" TargetName="popup" Value="true"/>
                    </DataTrigger.Setters>
                    <DataTrigger.EnterActions>
                        <BeginStoryboard x:Name="fadeInStoryboard">
                            <Storyboard>
                                <DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="errorBorder" Storyboard.TargetProperty="Opacity" To="1"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <StopStoryboard BeginStoryboardName="fadeInStoryboard"/>
                        <BeginStoryboard x:Name="fadeOutStoryBoard">
                            <Storyboard>
                                <DoubleAnimation Duration="00:00:00" Storyboard.TargetName="errorBorder" Storyboard.TargetProperty="Opacity" To="0"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <TextBox x:Name="textbox" Width="200" Height="40"  Validation.ErrorTemplate="{StaticResource validationTemplate }">
            <TextBox.Text>
                <Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <local:NumberValidationRule ValidatesOnTargetUpdated="True" />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox Width="100" Height="50" HorizontalAlignment="Right"></TextBox>
    </Grid>
</Window>

5.效果

这个可以使用,不会出现白点,但是界面变化的时候,输入框不会跟着走。

第三种:

这是最完美的,也是最复杂的。

1.首先建立一个wpf程序

2.BindingBase类,用于属性通知

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp2
{
    public class BindingBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        //protected virtual void OnPropertyChanged(string propertyName)
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")//此处使用特性
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

3.IValidationExceptionHandler类,用于界面继承

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp2
{
    public interface IValidationExceptionHandler
    {
        /// <summary>
        /// 是否有效
        /// </summary>
        bool IsValid
        {
            get;
            set;
        }
    }
}

4.VM,MainViewModel类,继承BindingBase和IValidationExceptionHandler

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp2
{
    public class MainViewModel : BindingBase , IValidationExceptionHandler
    {
        public MainViewModel()
        {

        }

        private int name;

        public int Name
        {
            get { return name; }
            set
            {
                name = value; OnPropertyChanged();//OnPropertyChanged(nameof(name),使用特性,去掉括号的值
            }
        }

        private string number;

        public string Number
        {
            get { return number; }
            set
            {
                number = value; OnPropertyChanged();//OnPropertyChanged(nameof(name),使用特性,去掉括号的值
            }
        }

        private bool isValid = true;
        public bool IsValid
        {
            get
            {
                return isValid;
            }
            set
            {
                if (value == isValid)
                    return;
                isValid = value;
                OnPropertyChanged();
            }
        }
    }
}

5.NotifyAdorner类,用于提示

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace WpfApp2
{
    public class NotifyAdorner : Adorner
    {

        private VisualCollection _visuals;
        private Canvas _canvas;
        private Image _image;
        private TextBlock _toolTip;
        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="adornedElement"></param>
        /// <param name="errorMessage"></param>
        public NotifyAdorner(UIElement adornedElement, string errorMessage)
            : base(adornedElement)
        {
            _visuals = new VisualCollection(this);

            BuildNotifyStyle(errorMessage);

            _canvas = new Canvas();

            _canvas.Children.Add(_image);

            _visuals.Add(_canvas);

        }

        private void BuildNotifyStyle(string errorMessage)
        {
            _image = new Image()
            {
                Width = 24,
                Height = 24,
                Source = new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + "/img/error.png", UriKind.Absolute))
            };

            _toolTip = new TextBlock()
            {
                FontSize = 14,
                Text = errorMessage
            };

            _image.ToolTip = _toolTip;
        }

        protected override int VisualChildrenCount
        {
            get
            {
                return _visuals.Count;
            }
        }

        protected override Visual GetVisualChild(int index)
        {
            return _visuals[index];
        }

        public void ChangeToolTip(string errorMessage)
        {
            _toolTip.Text = errorMessage;
        }

        protected override Size MeasureOverride(Size constraint)
        {
            return base.MeasureOverride(constraint);
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            _canvas.Arrange(new Rect(finalSize));

            _image.Margin = new Thickness(finalSize.Width + 2, 0, 0, 0);

            return base.ArrangeOverride(finalSize);
        }
    }
}

6.RequiredRule类,继承ValidationRule,此处可以写多个验证数据的类

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace WpfApp2
{
    public class RequiredRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            if (value == null || string.IsNullOrEmpty(value.ToString()))
            {
                return new ValidationResult(false, "不能为空!");
            }

            return new ValidationResult(true, null);
        }
    }
}

7.ValidationExceptionBehavior类,验证行为类,可以获得附加到的对象 

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Interactivity;

namespace WpfApp2
{
    /// <summary>
    /// 验证行为类,可以获得附加到的对象
    /// </summary>
    public class ValidationExceptionBehavior : Behavior<FrameworkElement>
    {

        #region 字段
        /// <summary>
        /// 错误计数器
        /// </summary>
        private int _validationExceptionCount = 0;

        private Dictionary<UIElement, NotifyAdorner> _adornerCache;
        #endregion

        #region 方法

        #region 重写方法
        /// <summary>
        /// 附加对象时
        /// </summary>
        protected override void OnAttached()
        {
            _adornerCache = new Dictionary<UIElement, NotifyAdorner>();

            //附加对象时,给对象增加一个监听验证错误事件的能力,注意该事件是冒泡的
            this.AssociatedObject.AddHandler(Validation.ErrorEvent, new EventHandler<ValidationErrorEventArgs>(this.OnValidationError));
        }

        #endregion

        #region 私有方法

        #region 获取实现接口的对象

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <returns></returns>
        private IValidationExceptionHandler GetValidationExceptionHandler()
        {
            if (this.AssociatedObject.DataContext is IValidationExceptionHandler)
            {
                var handler = this.AssociatedObject.DataContext as IValidationExceptionHandler;

                return handler;
            }

            return null;
        }

        #endregion

        #region 显示Adorner

        /// <summary>
        /// 显示Adorner
        /// </summary>
        /// <param name="element"></param>
        /// <param name="errorMessage"></param>
        private void ShowAdorner(UIElement element, string errorMessage)
        {
            NotifyAdorner adorner = null;

            //先去缓存找
            if (_adornerCache.ContainsKey(element))
            {
                adorner = _adornerCache[element];

                //找到了,修改提示信息
                adorner.ChangeToolTip(errorMessage);
            }
            //没有找到,那就New一个,加入到缓存
            else
            {
                adorner = new NotifyAdorner(element, errorMessage);

                _adornerCache.Add(element, adorner);
            }

            //将Adorner加入到
            if (adorner != null)
            {
                var adornerLayer = AdornerLayer.GetAdornerLayer(element);

                adornerLayer.Add(adorner);
            }
        }

        #endregion

        #region 移除Adorner

        /// <summary>
        /// 移除Adorner
        /// </summary>
        /// <param name="element"></param>
        private void HideAdorner(UIElement element)
        {
            //移除Adorner
            if (_adornerCache.ContainsKey(element))
            {
                var adorner = _adornerCache[element];

                var adornerLayer = AdornerLayer.GetAdornerLayer(element);

                adornerLayer.Remove(adorner);
            }
        }

        #endregion

        #region 验证事件方法

        /// <summary>
        /// 验证事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnValidationError(object sender, ValidationErrorEventArgs e)
        {
            try
            {
                var handler = GetValidationExceptionHandler();

                var element = e.OriginalSource as UIElement;

                if (handler == null || element == null)
                    return;

                if (e.Action == ValidationErrorEventAction.Added)
                {
                    _validationExceptionCount++;

                    ShowAdorner(element, e.Error.ErrorContent.ToString());
                }
                else if (e.Action == ValidationErrorEventAction.Removed)
                {
                    _validationExceptionCount--;

                    HideAdorner(element);
                }

                handler.IsValid = _validationExceptionCount == 0;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #endregion

        #endregion


    }
}

8.xaml界面

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <i:Interaction.Behaviors>
        <local:ValidationExceptionBehavior/>
    </i:Interaction.Behaviors>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <TextBox Height="25" Width="150">
            <TextBox.Text>
                <Binding Path="Number" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
                    <Binding.ValidationRules>
                        <local:RequiredRule ValidatesOnTargetUpdated="True"></local:RequiredRule>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>

        <TextBox Height="25" Width="150" Grid.Row="1">
            <TextBox.Text>
                <Binding Path="Name" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
                    <Binding.ValidationRules>
                        <local:RequiredRule ValidatesOnTargetUpdated="True"></local:RequiredRule>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>

        <!--<Button Width="100" Height="30" Grid.Row="2"  Content="确定" Command="{Binding OkCommand}"></Button>-->
    </Grid>
</Window>

最后别忘记进行关联

  this.DataContext = new MainViewModel();

9.效果

 源码:

https://download.csdn.net/download/u012563853/86522132

扩展:

效果

输入66是正常的,空的话报错空,其他报错误字样

1.建立一个项目

2.RequireValidate.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace WpfApp6
{
    public class RequireValidate : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            var str = value as string;
            //return ValidationResult.ValidResult;
            if (str == "66")
            {
                return new ValidationResult(true, "1");
            }
            else if (string.IsNullOrEmpty(str))
            {
                return new ValidationResult(false, "不能为空");
            }
            else
            {
                return new ValidationResult(false, "错误");
            }

        }
    }
}

3.MainWindow.xaml

<Window x:Class="WpfApp6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp6"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:RequireValidate x:Key="bb"/>
    </Window.Resources>
    <Grid>
        <TextBox Width="50" Height="50">
            <TextBox.Text>
                <Binding Path="A" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"  NotifyOnValidationError="True"  >
                    <Binding.ValidationRules >
                        <local:RequireValidate ValidatesOnTargetUpdated="True"  />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
            <Validation.ErrorTemplate>
                <ControlTemplate>
                    <StackPanel>
                        <Border BorderBrush="Red" BorderThickness="1">
                            <AdornedElementPlaceholder/>
                        </Border>
                        <TextBlock Foreground="Red" Text="{Binding [0].ErrorContent}"/>
                    </StackPanel>
                </ControlTemplate>
            </Validation.ErrorTemplate>
        </TextBox>
        
    </Grid>
</Window>

3.后台绑定A值即可 

源码: 

https://download.csdn.net/download/u012563853/88585307

来源:WPF-数据验证《十一》_wpf notifyadorner-CSDN博客

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
WPF 中,数据验证是一个重要的主题。WPF 中的数据验证分为两种:验证数据模型和验证用户界面输入。前者通常是通过使用数据模型中的属性和方法来完成的,而后者通常是通过使用 WPF数据绑定功能来完成的。 在本文中,我们将重点讨论如何使用 WPF数据绑定功能来验证用户界面输入。 WPF 中的数据绑定提供了两种验证方式:基于属性的验证和基于规则的验证。基于属性的验证是针对单个属性进行的验证,而基于规则的验证则是针对整个对象进行的验证。 基于属性的验证可以通过设置属性的 Metadata 来实现。例如,可以使用 RequiredAttribute 来标记属性为必填项。当用户尝试提交表单并且未填写必填项时,WPF 将会自动显示错误提示信息。 基于规则的验证可以通过实现 IDataErrorInfo 接口来实现。该接口包含两个属性:Error 和 Item。Error 属性用于返回整个对象的错误信息,而 Item 属性用于返回单个属性的错误信息。 下面是一个示例,演示如何使用 IDataErrorInfo 接口来实现基于规则的验证: ```csharp public class Person : IDataErrorInfo { public string Name { get; set; } public int Age { get; set; } public string this[string columnName] { get { string error = null; switch (columnName) { case "Name": if (string.IsNullOrEmpty(Name)) error = "Name is required."; break; case "Age": if (Age < 0 || Age > 120) error = "Age must be between 0 and 120."; break; } return error; } } public string Error { get { return null; } } } ``` 在上面的示例中,我们实现了 IDataErrorInfo 接口,并使用 switch 语句检查每个属性的值。如果属性的值不符合要求,我们就返回一个错误信息。在 XAML 中,可以使用 Binding.ValidationRules 属性来指定要使用的验证规则。 ```xaml <TextBox Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> <TextBox Text="{Binding Path=Age, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> ``` 在上面的示例中,我们将 ValidatesOnDataErrors 属性设置为 True,以启用基于规则的验证。当用户尝试提交表单时,WPF 将自动检查数据模型中的属性并显示错误提示信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

故里2130

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值