本文介绍了WPF文本框验证C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有3个文本框( Id1 名称工资)。 Id 薪水应该包含整数,名称应该只包含人物。我需要验证我的TextBox,它应该显示错误,因为我输入错误的字符或整数。也可以这样做只在Xaml没有codebehind?我是新的Wpf和验证请帮助我所需的代码

I have 3 TextBoxes (Id1,Name and Salary). Id and Salary should contain integers and Name should only contain characters. I need validations for my TextBox, it should show errors as I enter wrong characters or integers. Also can this be done only in Xaml without codebehind? I'm new to Wpf and validation please help me with the required code

这是Xaml代码:

<TextBox Name="tb1" HorizontalAlignment="Left" Height="20" Margin="60,10,0,0" TextWrapping="NoWrap" Text="{Binding SelectedItem.Id,ElementName=dgsample}" VerticalAlignment="Top" Width="100" />
<TextBox Name="tb2" HorizontalAlignment="Left" Height="20" Margin="60,60,0,0" TextWrapping="NoWrap" Text="{Binding SelectedItem.Name, ElementName=dgsample}" VerticalAlignment="Top" Width="100"/>
<TextBox Name="tb3" HorizontalAlignment="Left" Height="20" Margin="60,110,0,0" TextWrapping="NoWrap" Text="{Binding SelectedItem.Salary, ElementName=dgsample}" VerticalAlignment="Top" Width="100"/>


推荐答案

有3种方法来实现验证:


There a 3 ways to implement validation:


  1. 验证规则

  2. 执行 INotifyDataErrorInfo

  3. 实现 IDataErrorInfo

  1. Validation Rule
  2. Implementation of INotifyDataErrorInfo
  3. Implementation of IDataErrorInfo

验证规则示例

 public class NumericValidationRule : ValidationRule
    {
        public Type ValidationType { get; set; }
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            string strValue = Convert.ToString(value);

            if (string.IsNullOrEmpty(strValue))
                return new ValidationResult(false, $"Value cannot be coverted to string.");
            bool canConvert = false;
            switch (ValidationType.Name)
            {

                case "Boolean":
                    bool boolVal = false;
                    canConvert = bool.TryParse(strValue, out boolVal);
                    return canConvert ? new ValidationResult(true, null) : new ValidationResult(false, $"Input should be type of boolean");
                case "Int32":
                    int intVal = 0;
                    canConvert = int.TryParse(strValue, out intVal);
                    return canConvert ? new ValidationResult(true, null) : new ValidationResult(false, $"Input should be type of Int32");
                case "Double":
                    double doubleVal = 0;
                    canConvert = double.TryParse(strValue, out doubleVal);
                    return canConvert ? new ValidationResult(true, null) : new ValidationResult(false, $"Input should be type of Double");
                case "Int64":
                    long longVal = 0;
                    canConvert = long.TryParse(strValue, out longVal);
                    return canConvert ? new ValidationResult(true, null) : new ValidationResult(false, $"Input should be type of Int64");
                default:
                    throw new InvalidCastException($"{ValidationType.Name} is not supported");
            }
        }
    }

XAML:

非常重要:不要忘记设置 ValidatesOnTargetUpdated =True它不会工作没有这个定义。

Very important: don't forget to set ValidatesOnTargetUpdated="True" it won't work without this definition.

 <TextBox x:Name="Int32Holder"
                                 IsReadOnly="{Binding IsChecked,ElementName=CheckBoxEditModeController,Converter={converters:BooleanInvertConverter}}"
                                 Style="{StaticResource ValidationAwareTextBoxStyle}"
                                 VerticalAlignment="Center">
                            <!--Text="{Binding Converter={cnv:TypeConverter}, ConverterParameter='Int32', Path=ValueToEdit.Value, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"-->
                            <TextBox.Text>
                                <Binding Path="Name"
                                         Mode="TwoWay"
                                         UpdateSourceTrigger="PropertyChanged"
                                         Converter="{cnv:TypeConverter}"
                                         ConverterParameter="Int32"
                                         ValidatesOnNotifyDataErrors="True"
                                         ValidatesOnDataErrors="True"
                                         NotifyOnValidationError="True">
                                    <Binding.ValidationRules>
                                        <validationRules:NumericValidationRule ValidationType="{x:Type system:Int32}"
                                                                               ValidatesOnTargetUpdated="True" />
                                    </Binding.ValidationRules>
                                </Binding>
                            </TextBox.Text>
                            <!--NumericValidationRule-->
                        </TextBox>

INotifyDataErrorInfo示例

 public abstract class ViewModelBase : INotifyPropertyChanged, INotifyDataErrorInfo
    {

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            ValidateAsync();
        }
        #endregion


        public virtual void OnLoaded()
        {
        }

        #region INotifyDataErrorInfo
        private ConcurrentDictionary<string, List<string>> _errors = new ConcurrentDictionary<string, List<string>>();

        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        public void OnErrorsChanged(string propertyName)
        {
            var handler = ErrorsChanged;
            if (handler != null)
                handler(this, new DataErrorsChangedEventArgs(propertyName));
        }

        public IEnumerable GetErrors(string propertyName)
        {
            List<string> errorsForName;
            _errors.TryGetValue(propertyName, out errorsForName);
            return errorsForName;
        }

        public bool HasErrors
        {
            get { return _errors.Any(kv => kv.Value != null && kv.Value.Count > 0); }
        }

        public Task ValidateAsync()
        {
            return Task.Run(() => Validate());
        }

        private object _lock = new object();
        public void Validate()
        {
            lock (_lock)
            {
                var validationContext = new ValidationContext(this, null, null);
                var validationResults = new List<ValidationResult>();
                Validator.TryValidateObject(this, validationContext, validationResults, true);

                foreach (var kv in _errors.ToList())
                {
                    if (validationResults.All(r => r.MemberNames.All(m => m != kv.Key)))
                    {
                        List<string> outLi;
                        _errors.TryRemove(kv.Key, out outLi);
                        OnErrorsChanged(kv.Key);
                    }
                }

                var q = from r in validationResults
                        from m in r.MemberNames
                        group r by m into g
                        select g;

                foreach (var prop in q)
                {
                    var messages = prop.Select(r => r.ErrorMessage).ToList();

                    if (_errors.ContainsKey(prop.Key))
                    {
                        List<string> outLi;
                        _errors.TryRemove(prop.Key, out outLi);
                    }
                    _errors.TryAdd(prop.Key, messages);
                    OnErrorsChanged(prop.Key);
                }
            }
        }
        #endregion

    }

查看模型实现:

 public class MainFeedViewModel : BaseViewModel//, IDataErrorInfo
    {
        private ObservableCollection<FeedItemViewModel> _feedItems;
        [XmlIgnore]
        public ObservableCollection<FeedItemViewModel> FeedItems
        {
            get
            {
                return _feedItems;
            }
            set
            {
                _feedItems = value;
                OnPropertyChanged("FeedItems");
            }
        }
        [XmlIgnore]
        public ObservableCollection<FeedItemViewModel> FilteredFeedItems
        {
            get
            {
                if (SearchText == null) return _feedItems;

                return new ObservableCollection<FeedItemViewModel>(_feedItems.Where(x => x.Title.ToUpper().Contains(SearchText.ToUpper())));
            }
        }

        private string _title;
        [Required]
        [StringLength(20)]
        //[CustomNameValidationRegularExpression(5, 20)]
        [CustomNameValidationAttribute(3, 20)]
        public string Title
        {
            get { return _title; }
            set
            {
                _title = value;
                OnPropertyChanged("Title");
            }
        }
        private string _url;
        [Required]
        [StringLength(200)]
        [Url]
        //[CustomValidation(typeof(MainFeedViewModel), "UrlValidation")]
        /// <summary>
        /// Validation of URL should be with custom method like the one that implemented below, or with
        /// </summary>
        public string Url
        {
            get { return _url; }
            set
            {
                _url = value;
                OnPropertyChanged("Url");
            }
        }

        public MainFeedViewModel(string url, string title)
        {
            Title = title;
            Url = url;
        }
        /// <summary>
        ///
        /// </summary>
        public MainFeedViewModel()
        {

        }
        public MainFeedViewModel(ObservableCollection<FeedItemViewModel> feeds)
        {
            _feedItems = feeds;
        }


        private string _searchText;
        [XmlIgnore]
        public string SearchText
        {
            get { return _searchText; }
            set
            {
                _searchText = value;

                OnPropertyChanged("SearchText");
                OnPropertyChanged("FilteredFeedItems");
            }
        }

        #region Data validation local
        /// <summary>
        /// Custom URL validation method
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public static ValidationResult UrlValidation(object obj, ValidationContext context)
        {
            var vm = (MainFeedViewModel)context.ObjectInstance;
            if (!Uri.IsWellFormedUriString(vm.Url, UriKind.Absolute))
            {
                return new ValidationResult("URL should be in valid format", new List<string> { "Url" });
            }
            return ValidationResult.Success;
        }

        #endregion
    }

XAML :

<UserControl x:Class="RssReaderTool.Views.AddNewFeedDialogView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="300"
             d:DesignWidth="300">
    <FrameworkElement.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate x:Name="TextErrorTemplate">
                        <DockPanel LastChildFill="True">
                            <AdornedElementPlaceholder>
                                <Border BorderBrush="Red"
                                        BorderThickness="2" />
                            </AdornedElementPlaceholder>
                            <TextBlock FontSize="20"
                                       Foreground="Red">*?*</TextBlock>
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="Validation.HasError"
                         Value="True">
                    <Setter Property="ToolTip"
                            Value="{Binding RelativeSource=
            {x:Static RelativeSource.Self},
            Path=(Validation.Errors)[0].ErrorContent}"></Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
        <!--<Style 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)[0].ErrorContent}" />
                </Trigger>
            </Style.Triggers>
        </Style>-->
    </FrameworkElement.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="5" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="5" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="5" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBlock Text="Feed Name"
                   ToolTip="Display" />
        <TextBox Text="{Binding MainFeedViewModel.Title,UpdateSourceTrigger=PropertyChanged,ValidatesOnNotifyDataErrors=True,ValidatesOnDataErrors=True}"
                 Grid.Column="2" />

        <TextBlock Text="Feed Url"
                   Grid.Row="2" />
        <TextBox Text="{Binding MainFeedViewModel.Url,UpdateSourceTrigger=PropertyChanged,ValidatesOnNotifyDataErrors=True,ValidatesOnDataErrors=True}"
                 Grid.Column="2"
                 Grid.Row="2" />
    </Grid>
</UserControl>

IDataErrorInfo

查看模型:

public class OperationViewModel : ViewModelBase, IDataErrorInfo
    {
        private const int ConstCodeMinValue = 1;
        private readonly IEventAggregator _eventAggregator;
        private OperationInfoDefinition _operation;
        private readonly IEntityFilterer _contextFilterer;
        private OperationDescriptionViewModel _description;

        public long Code
        {
            get { return _operation.Code; }
            set
            {
                if (SetProperty(value, _operation.Code, o => _operation.Code = o))
                {
                    UpdateDescription();
                }
            }
        }

        public string Description
        {
            get { return _operation.Description; }
            set
            {
                if (SetProperty(value, _operation.Description, o => _operation.Description = o))
                {
                    UpdateDescription();
                }
            }
        }

        public string FriendlyName
        {
            get { return _operation.FriendlyName; }
            set
            {
                if (SetProperty(value, _operation.FriendlyName, o => _operation.FriendlyName = o))
                {
                    UpdateDescription();
                }
            }
        }

        public int Timeout
        {
            get { return _operation.Timeout; }
            set
            {
                if (SetProperty(value, _operation.Timeout, o => _operation.Timeout = o))
                {
                    UpdateDescription();
                }
            }
        }

        public string Category
        {
            get { return _operation.Category; }
            set
            {
                if (SetProperty(value, _operation.Category, o => _operation.Category = o))
                {
                    UpdateDescription();
                }
            }
        }

        public bool IsManual
        {
            get { return _operation.IsManual; }
            set
            {
                if (SetProperty(value, _operation.IsManual, o => _operation.IsManual = o))
                {
                    UpdateDescription();
                }
            }
        }


        void UpdateDescription()
        {
            //some code
        }




        #region Validation




        #region IDataErrorInfo

        public ValidationResult Validate()
        {
            return ValidationService.Instance.ValidateNumber(Code, ConstCodeMinValue, long.MaxValue);
        }

        public string this[string columnName]
        {
            get
            {
                var validation = ValidationService.Instance.ValidateNumber(Code, ConstCodeMinValue, long.MaxValue);

                return validation.IsValid ? null : validation.ErrorContent.ToString();
            }
        }

        public string Error
        {
            get
            {
                var result = Validate();
                return result.IsValid ? null : result.ErrorContent.ToString();
            }
        }
        #endregion

        #endregion
    }

XAML:

<controls:NewDefinitionControl x:Class="DiagnosticsDashboard.EntityData.Operations.Views.NewOperationView"
                               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                               xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                               xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                               xmlns:views="clr-namespace:DiagnosticsDashboard.EntityData.Operations.Views"
                               xmlns:controls="clr-namespace:DiagnosticsDashboard.Core.Controls;assembly=DiagnosticsDashboard.Core"
                               xmlns:c="clr-namespace:DiagnosticsDashboard.Core.Validation;assembly=DiagnosticsDashboard.Core"
                               mc:Ignorable="d">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Label Grid.Column="0"
               Grid.Row="0"
               Margin="5">Code:</Label>
        <Label Grid.Column="0"
               Grid.Row="1"
               Margin="5">Description:</Label>
        <Label Grid.Column="0"
               Grid.Row="2"
               Margin="5">Category:</Label>
        <Label Grid.Column="0"
               Grid.Row="3"
               Margin="5">Friendly Name:</Label>
        <Label Grid.Column="0"
               Grid.Row="4"
               Margin="5">Timeout:</Label>
        <Label Grid.Column="0"
               Grid.Row="5"
               Margin="5">Is Manual:</Label>
        <TextBox Grid.Column="1"
                 Text="{Binding Code,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}"
                 Grid.Row="0"
                 Margin="5"/>
        <TextBox Grid.Column="1"
                 Grid.Row="1"
                 Margin="5"
                 Text="{Binding Description}" />
        <TextBox Grid.Column="1"
                 Grid.Row="2"
                 Margin="5"
                 Text="{Binding Category}" />
        <TextBox Grid.Column="1"
                 Grid.Row="3"
                 Margin="5"
                 Text="{Binding FriendlyName}" />
        <TextBox Grid.Column="1"
                 Grid.Row="4"
                 Margin="5"
                 Text="{Binding Timeout}" />
        <CheckBox Grid.Column="1"
                  Grid.Row="5"
                  Margin="5"
                  IsChecked="{Binding IsManual}"
                  VerticalAlignment="Center" />


    </Grid>
</controls:NewDefinitionControl>

这篇关于WPF文本框验证C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-28 04:32
查看更多