WPF --- TextBox的輸入校驗

来源:https://www.cnblogs.com/pandefu/archive/2023/11/16/17837358.html
-Advertisement-
Play Games

引言 在WPF應用程式開發中,數據校驗是確保用戶輸入數據的正確性和完整性的重要一環。 之前在做一些參數配置功能時,最是頭疼各種參數校驗,查閱一些資料後,我總結了數據校驗方式有兩種: ValidationRule IDataErrorInfo 接下來分別介紹這兩種校驗方式。 ValidationRul ...


引言

在WPF應用程式開發中,數據校驗是確保用戶輸入數據的正確性和完整性的重要一環。

之前在做一些參數配置功能時,最是頭疼各種參數校驗,查閱一些資料後,我總結了數據校驗方式有兩種:

  • ValidationRule
  • IDataErrorInfo

接下來分別介紹這兩種校驗方式。

ValidationRule

ValidationRule 是一個抽象類,提供了抽象方法 Validate(), 它是WPF中用於數據驗證的一種機制,它可以在用戶輸入數據之前或之後執行自定義的驗證邏輯。可以輕鬆地實現對數據的格式、範圍、邏輯等方面的驗證,併在驗證失敗時提供相應的反饋信息。

ValidationRule主要作用域在前端頁面上

基本用法

首先創建一個 ValidationRule,我這裡設定了兩個屬性 MaxValMinVal,然後在 Validate() 方法中判斷空、判斷大於上限或小於下限,然後在符合條件是,返回 ValidationResult,並給出錯誤提示:

public class IntegerValidationRule : ValidationRule
{
    public int MaxVal { get; set; }
    public int MinVal { get; set; }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        string text = value as string;

        if (!int.TryParse(text, out int result))
        {
            return new ValidationResult(false, "Text cannot be empty.");
        }

        if (result > MaxVal)
        {
            return new ValidationResult(false, "Value out of upper limit range.");
        }

        if (result < MinVal)
        {
            return new ValidationResult(false, "Value out of lower limit range.");
        }

        return ValidationResult.ValidResult;
    }
}

接下來創建有個測試使用的 ViewModel:

public class TestViewModel : INotifyPropertyChanged
{
    private TestViewModel() { }

    public static TestViewModel Instance { get; } = new TestViewModel();

    public event PropertyChangedEventHandler? PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private int testField1;
    /// <summary>
    /// 測試屬性1
    /// </summary>
    public int TestField1
    {
        get => testField1;
        set
        {
            testField1 = value;
            OnPropertyChanged(nameof(TestField1));
        }
    }

    private int testField2;
    /// <summary>
    /// 測試屬性2
    /// </summary>
    public int TestField2
    {
        get => testField2;
        set
        {
            testField2 = value;
            OnPropertyChanged(nameof(TestField2));
        }
    }
}


在測試之前,我們可以先看一下 Binding 的方法列表:

image.png

可以看到 ValidationRulesBinding 下的集合,這意味著 ValidationRule 是在 Binding 下使用且可以執行多個校驗規則。校驗時按照順序依次校驗。

接下來我們創建一個WPF應用程式,在界面添加 TextBox,命名為”textbox1“,將文本綁定在 TestViewModelTestField1

且為Validation.ErrorTemplate 綁定一個模板,這裡綁定了一個紅色的感嘆號。

然後為 TextBox 設置觸發器,當 Validation.HasErrortrue時,將 ToolTip 綁定校驗失敗的錯誤提示。

代碼如下:

<Window
    x:Class="WpfApp4.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:local="clr-namespace:WpfApp4"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="900"
    Height="450"
    mc:Ignorable="d">
    <Window.Resources>
        <ControlTemplate x:Key="ValidationTemplate">
            <DockPanel>
                <TextBlock
                    Margin="-10,0,0,0"
                    VerticalAlignment="Center"
                    FontSize="22"
                    Foreground="Red"
                    Text="!" />

            </DockPanel>
        </ControlTemplate>

        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0">
            <TextBlock
                HorizontalAlignment="Center"
                FontSize="18"
                FontWeight="Bold"
                Text="Validation Demo" />
            <TextBox
                Name="textBox1"
                Height="30"
                Margin="10"
                FontSize="22"
                Validation.ErrorTemplate="{StaticResource ValidationTemplate}">
                <TextBox.Text>
                    <Binding Path="TestField1" UpdateSourceTrigger="PropertyChanged">
                        <Binding.ValidationRules>
                            <local:IntegerValidationRule
                                MaxVal="999"
                                MinVal="5" />
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>

        </StackPanel>
    </Grid>
</Window>

最後在窗體後臺綁定 ViewModel:

public MainWindow()
{
    InitializeComponent();
    this.DataContext =  TestViewModel.Instance;
}

測試

  1. 為空時,出現紅色嘆號,ToolTip 提示 "Text cannot be empty."
    image.png

  2. 小於下限時,出現紅色嘆號,ToolTip 提示 "Value out of lower limit range."
    image.png

  3. 大於上限時,出現紅色嘆號,ToolTip 提示 "Value out of upper limit range."
    image.png

IDataErrorInfo

IDataErrorInfo 是一個介面,Viewmodel 實現介面用於在後臺,提供數據驗證和錯誤信息。

IDataErrorInfo 主要作用域為後臺 ViewModel
該介面包含兩個成員:Errorthis[string columnName]。這兩個成員允許你在數據綁定時提供驗證錯誤信息。

基本用法

接下來,在程式里添加 TextBox,命名為”textbox2“,並添加一個 TextBlock 綁定 Error 展示在界面。

<StackPanel Grid.Column="1">
    <TextBlock
        HorizontalAlignment="Center"
        FontSize="18"
        FontWeight="Bold"
        Text="IDataErrorInfo Demo" />
    <TextBox
        Name="textBox2"
        Margin="10"
        VerticalAlignment="Center"
        FontSize="22"
        Text="{Binding TestField2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
     <TextBlock
         HorizontalAlignment="Center"
         FontSize="18"
         FontWeight="Bold"
         Foreground="Red"
         Text="{Binding Error, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>

後臺 TestViweModel 實現 IDataErrorInfo,依舊是判斷上限值和下限值,此處不判斷空,是因為後臺 TestField2 類型是Int,為空時不會賦值,代碼如下:

public class TestViewModel : INotifyPropertyChanged, IDataErrorInfo
{
    //省略上文已有代碼..。
    
    private string error;
    public string Error
    {
        get => error;
        set
        {
            error = value; OnPropertyChanged(nameof(Error));
        }
    }
    public string this[string columnName]
    {
        get
        {
            switch (columnName)
            {
                case nameof(TestField2):
                    return CheckTestFild2();
                default:
                    return null;
            }
        }
    }

    public int MaxVal = 999;
    public int MinVal = 5;

    private string CheckTestFild2()
    {
        if (TestField2 > MaxVal)
        {
            Error = "Value out of upper limit range in viewmodel.";
        }
        else if (TestField2 < MinVal)
        {
            Error = "Value out of lower limit range  in viewmodel.";
        }
        else
        {
            Error = string.Empty;
        }
        
        return Error;
    }
}

測試

  1. 小於下限時,出現紅色文字提示,ToolTip 提示 "Value out of lower limit range in viewmodel."
    image.png

  2. 大於上限時,出現紅色文字提示,ToolTip 提示 "Value out of upper limit range in viewmodel."
    image.png

小結

以上兩種數據校驗(IDataErrorInfoValidationRule)的方式,均可以實現自定義數據校驗,例如對數據的格式、範圍、邏輯等方面的驗證,併在驗證失敗時提供相應的反饋信息。

ValidationRule適用於在界面做數據校驗,且可以定義多個校驗規則。

ValidationRule適用於在ViewModel做數據校驗,可以做一些無法在前端頁面做的事情,比如出現異常值是還原為預設值。

所以兩者既可以單獨使用,也可以組合使用,即使使用MVVM模式,依舊能夠優雅的做數據校驗。

作者: Niuery Daily

出處: https://www.cnblogs.com/pandefu/>

郵箱: [email protected]

關於作者:.Net Framework,.Net Core ,WindowsForm,WPF ,控制項庫,多線程

本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出 原文鏈接,否則保留追究法律責任的權利。 如有問題, 可郵件咨詢。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 將Excel文件轉換為PDF可以方便儲存表格數據,此外在列印或共用文檔時也能確保表格樣式佈局等在不同設備和操作系統上保持一致。今天給大家分享一個使用第三方Python庫Spire.XLS for Python 實現Excel轉PDF的簡單方法。 Python中Excel轉PDF的實現步驟 1. 首先 ...
  • golang 的 map 使用的是 hash map 基本結構 下麵截取自源碼,已翻譯 // runtime/map.go:117 // go map 定義,hashmap 縮寫 type hmap struct { count int // map 里文件數 flags uint8 // map ...
  • 二叉樹初步: 代碼如下,註釋很詳細。 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstring> #include <stdlib.h> #include <stdio.h> #include <math.h> #in ...
  • 如何用Java設計自動售貨機?是大多在高級Java開發人員面試中經常被問到的好問題之一。在典型的編碼面試中,你會得到一個問題描述來開發一個售貨機,在有限的時間內,通常2到3小時內,你需要在Java中編寫設計文檔、工作代碼和單元測試。這種Java面試的一個關鍵優勢是可以一次測試候選人的許多基本技能。為 ...
  • 公眾號「架構成長指南」,專註於生產實踐、雲原生、分散式系統、大數據技術分享。 在之前的幾個教程中,我們學了: 使用 RestTemplate 的 Spring Boot 微服務通信示例 使用 WebClient 的 Spring Boot 微服務通信示例 使用 Spring Cloud Open F ...
  • 學習視頻:【孫哥說Spring5:從設計模式到基本應用到應用級底層分析,一次深入淺出的Spring全探索。學不會Spring?只因你未遇見孫哥】 第七章、反轉控制與依賴註入 1.反轉(轉移)控制(IOC inverse of Control) 控制:對於成員變數賦值的控制權 反轉控制:把對於成員變數 ...
  • 在Java中創建多線程,往往都要通過Thread類來實現,今天學習下Java中創建多線程的三種方法[1]。 1.繼承Thread類 通過繼承 Thread類 實現多線程。 主要方法: 1.void run(), 線程開啟後,方法將被調用執行 2.void start(), 使此線程開始執行, Jav ...
  • Scipy的ODR正交距離回歸(ODR-Orthogonal Distance Regression)模塊,適用於回歸分析時,因變數和自變數之間存在非線性關係的情況。它提高了回歸分析的準確性和穩健性。對於需要解決非線性回歸問題的科研人員和工程師來說,它具有非常重要的意義。 ODR正交距離回歸模塊的作 ...
一周排行
    -Advertisement-
    Play Games
  • 當使用Autofac處理一個介面有多個實現的情況時,通常會使用鍵(key)進行區分或者通過IIndex索引註入,也可以通過IEnumerable集合獲取所有實例,以下是一個具體的例子,演示如何在Autofac中註冊多個實現,並通過構造函數註入獲取指定實現。 首先,確保你已經安裝了Autofac Nu ...
  • 本篇將分享Prometheus+Grafana的監控平臺搭建,並監控之前文章所搭建的主機&服務,分享日常使用的一些使用經驗本篇將配置常用服務的監控與面板配置:包括 MySQL,MongoDB,CLickHouse,Redis,RabbitMQ,Linux,Windows,Nginx,站點訪問監控,已... ...
  • 使用Aspirate可以將Aspire程式部署到Kubernetes 集群 工具安裝 dotnet tool install -g aspirate --prerelease 註意:Aspirate 正在開發中,該軟體包將作為預覽版進行版本控制,--prelease 選項將獲得最新的預覽版。 容器註 ...
  • 前言 本文要說的這種開發模式,這種模式並不是只有blazor支持,js中有一樣的方案next.js nuxt.js;blazor還有很多其它內容,本文近關註漸進式開發模式。 是的,前後端是主流,不過以下情況也許前後端分離並不是最好的選擇: 小公司,人員不多,利潤不高,創業階段能省則省 個人開發者,接 ...
  • 在.NET中,Microsoft.Extensions.Logging是一個靈活的日誌庫,它允許你將日誌信息記錄到各種不同的目標,包括資料庫。在這個示例中,我將詳細介紹如何使用Microsoft.Extensions.Logging將日誌保存到MySQL資料庫。我們將使用Entity Framewo ...
  • chatgpt介面開發筆記3: 語音識別介面 1.文本轉語音 1、瞭解介面參數 介面地址: POST https://api.openai.com/v1/audio/speech 下麵是介面文檔描述內容: 參數: { "model": "tts-1", "input": "你好,我是饒坤,我是ter ...
  • 前面兩篇文章主要是介紹瞭如何解決高併發情況下資源爭奪的問題。但是現實的應用場景中除了要解決資源爭奪問題,高併發的情況還需要解決更多問題,比如快速處理業務數據等, 本篇文章簡要羅列一下與之相關的更多技術細節。 1、非同步編程:使用async和await關鍵字進行非同步編程,這可以避免阻塞線程,提高程式的響 ...
  • 大家好,我是棧長。 Nacos 2.3.0 前幾天正式發佈了,新增了不少實用性的新功能,真是史上最強版本。 Nacos 2.3.0 還真是一個比較重要的大版本,因為它涉及了太多重大更新,今天棧長給大家來解讀下。 Nacos 先掃個盲: Nacos 一個用於構建雲原生應用的動態服務發現、配置管理和服務 ...
  • IDEA的遠程開發功能,可以將本地的編譯、構建、調試、運行等工作都放在遠程伺服器上執行,而本地僅運行客戶端軟體進行常規的開發操作即可,舊版本IDEA目前不支持該功能.,本例使用的是IDEA2023.2.5版本 下麵介紹如何在IDEA中設置遠程連接伺服器開發環境並結合Cpolar內網穿透工具實現無公網 ...
  • 本文解釋為啥會有響應式編程,為什麼它在開發者中不太受歡迎,以及引入 Java 虛擬線程後它可能最終會消失。 命令式風格編程一直深受開發者喜愛,如 if-then-else、while 迴圈、函數和代碼塊等結構使代碼易理解、調試,異常易追蹤。然而,像所有好的東西一樣,通常也有問題。這種編程風格導致線程 ...