wpf 自定义控件,只能输入小数点,并且能控制小数点位数

cs 复制代码
using System.Windows.Input;
using System.Windows;
using System.Windows.Controls;

namespace 项目名称
{
    public class DoubleTextBox : TextBox
    {
        public double? MinValue
        {
            get { return (double?)GetValue(MinValueProperty); }
            set { SetValue(MinValueProperty, value); }
        }

        public static readonly DependencyProperty MinValueProperty =
            DependencyProperty.Register("MinValue", typeof(double?), typeof(DoubleTextBox));

        public double MaxValue
        {
            get { return (double)GetValue(MaxValueProperty); }
            set { SetValue(MaxValueProperty, value); }
        }

        public static readonly DependencyProperty MaxValueProperty =
        DependencyProperty.Register("MaxValue", typeof(double), typeof(DoubleTextBox), new PropertyMetadata(double.MaxValue));

        public static bool GetIsEnabled(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsGotFocusProperty);
        }

        public static void SetIsEnabled(DependencyObject obj, bool value)
        {
            obj.SetValue(IsGotFocusProperty, value);
        }

        public bool IsNeedLoseFucos
        {
            get { return (bool)GetValue(IsNeedLoseFucosvProperty); }
            set { SetValue(IsNeedLoseFucosvProperty, value); }
        }
        public static readonly DependencyProperty IsNeedLoseFucosvProperty =
            DependencyProperty.RegisterAttached("IsNeedLoseFucos", typeof(bool), typeof(DoubleTextBox), new PropertyMetadata(true));

        public bool IsGotFocus
        {
            get { return (bool)GetValue(IsGotFocusProperty); }
            set { SetValue(IsGotFocusProperty, value); }
        }
        public static readonly DependencyProperty IsGotFocusProperty =
            DependencyProperty.RegisterAttached("IsGotFocus", typeof(bool), typeof(DoubleTextBox), new PropertyMetadata(false));

        public string PreviousText
        {
            get { return (string)GetValue(PreviousTextProperty); }
            set { SetValue(PreviousTextProperty, value); }
        }
        public static readonly DependencyProperty PreviousTextProperty =
            DependencyProperty.Register("PreviousText", typeof(string), typeof(DoubleTextBox), new PropertyMetadata(string.Empty));

        public int DecimalCount
        {
            get { return (int)GetValue(DecimalCountProperty); }
            set { SetValue(DecimalCountProperty, value); }
        }
        public static readonly DependencyProperty DecimalCountProperty =
            DependencyProperty.Register("DecimalCount", typeof(int), typeof(DoubleTextBox), new PropertyMetadata(3));

        public string HistoryText
        {
            get { return (string)GetValue(HistoryTextProperty); }
            set { SetValue(HistoryTextProperty, value); }
        }
        public static readonly DependencyProperty HistoryTextProperty = DependencyProperty.Register("HistoryText", typeof(string), typeof(DoubleTextBox), new PropertyMetadata(string.Empty));


        static DoubleTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DoubleTextBox), new FrameworkPropertyMetadata(typeof(DoubleTextBox)));
        }

        public DoubleTextBox()
        {
            LostFocus += DoubleTextBox_LostFocus;
            PreviewTextInput += DoubleTextBox_PreviewTextInput;
        }

        private void DoubleTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            Text = Text.Trim();
            string txt = Text + e.Text;

            if (!double.TryParse(txt, out double value))
            {
                if (!string.IsNullOrWhiteSpace(Text))
                {
                    var index = Text.IndexOf(e.Text);
                    if (index > -1) { Text = Text.Remove(index); }

                    SelectionStart = Text.Length + e.Text.Length;
                }
                e.Handled = true; // 阻止输入非数字字符
            }
            else if (value > MaxValue)
            {
                Text = MaxValue.ToString(); // 将文本框的值设置为最大值
                SelectionStart = Text.Length + e.Text.Length;
                e.Handled = true; // 阻止输入超出取值范围的数字
            }
            else if (txt.Contains('.'))
            {
                var Has = txt.Split('.');
                if (Has != null && Has.Length > 0 && Has[1] != null)
                {
                    if (Has[1].Length == DecimalCount)
                    {
                        double dis = double.Parse(txt);
                        if (MinValue is not null && dis < MinValue && txt.Length >= MinValue.Value.ToString().Length)
                        {
                            Text = MinValue.Value.ToString(); // 将文本框的值设置为最小值
                            SelectionStart = Text.Length + e.Text.Length;
                            e.Handled = true; // 阻止输入非数字字符
                        }
                    }
                    else if (Has[1].Length > DecimalCount)
                    {
                        Text = string.Format("{0:f" + DecimalCount + "}", value);
                        double dis = double.Parse(txt);
                        if (MinValue is not null && dis < MinValue && txt.Length >= MinValue.Value.ToString().Length)
                        {
                            Text = MinValue.Value.ToString(); // 将文本框的值设置为最小值
                        }
                        SelectionStart = Text.Length + e.Text.Length;
                        e.Handled = true; // 阻止输入非数字字符
                    }
                }
            }
            else
            {
                Text = value.ToString();
                SelectionStart = Text.Length + e.Text.Length;
                e.Handled = true;
            }
            SelectionStart = Text.Length + e.Text.Length;
            HistoryText = Text;
        }

        private void DoubleTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            IsGotFocus = false;

            Text = Text.Trim();
            if (string.IsNullOrEmpty(Text))
            {
                if (!string.IsNullOrEmpty(HistoryText) && double.TryParse(HistoryText, out double history) && history > MinValue)
                {
                    Text = HistoryText;
                }
                else if(!string.IsNullOrEmpty(PreviousText))
                {
                    Text = PreviousText;
                }
                else if (MinValue is not null)
                {
                    Text = MinValue.Value.ToString();
                }
                SelectionStart = Text.Length;
            }
            else
            {
                if (double.TryParse(Text, out double num))
                {
                    if (num < MinValue)
                    {
                        if (!string.IsNullOrEmpty(HistoryText) && double.TryParse(HistoryText, out double history) && history > MinValue)
                        {
                            Text = HistoryText;
                        }
                        else
                        {
                            Text = MinValue.ToString();
                        }
                    }
                    else if (num > MaxValue)
                    {
                        if (!string.IsNullOrEmpty(HistoryText) && double.TryParse(HistoryText, out double history) && history < MaxValue)
                        {
                            Text = HistoryText;
                        }
                        else if (!string.IsNullOrEmpty(PreviousText))
                        {
                            Text = PreviousText;
                        }
                        else
                        {
                            Text = MaxValue.ToString();
                        }
                    }
                }
            }
        }
    }
}

调用:DecimalCount就是小数点位数,一般不去设置,最多三位小数点。如果失去焦点,当前的数据会时你上次输入的数据,这样不会出现数据为空的情况。

cs 复制代码
 xmlns:local="clr-namespace:你的项目名"  
        xmlns:sys="clr-namespace:System;assembly=mscorlib"  

<local:DoubleTextBox MinValue="0.001" MaxValue="1000000000" PreviousText="1" Text="{Binding Dilution,TargetNullValue={x:Static sys:String.Empty}}" 
                                 Width="183" Height="60" MaxLength="10" />
相关推荐
bugcome_com11 小时前
WPF样式进阶实战:外置样式+MVVM主题切换+样式优先级全解析
c#·.net·wpf
lalala_Zou19 小时前
场景题:电商平台订单未支付过期如何实现自动关闭订单?
wpf
czhc114007566319 小时前
wpf 16
wpf
cn_mengbei1 天前
鸿蒙PC原生应用开发实战:ArkTS与DevEco Studio从零构建跨端桌面应用全栈指南
华为·wpf·harmonyos
lingxiao168882 天前
WebApi详解+Unity注入--上篇:基于Framework的WebApi
c#·wpf·web
是一个Bug2 天前
Java后端开发面试题清单(50道) - 分布式基础
java·分布式·wpf
无心水2 天前
【分布式利器:腾讯TSF】4、TSF配置中心深度解析:微服务动态配置的终极解决方案
分布式·微服务·架构·wpf·分布式利器·腾讯tsf·分布式利器:腾讯tsf
lingxiao168882 天前
WebApi详解+Unity注入--下篇:Unity注入
unity·c#·wpf
无心水3 天前
【分布式利器:腾讯TSF】6、TSF可观测性体系建设实战:Java全链路Metrics+Tracing+Logging落地
java·分布式·架构·wpf·分布式利器·腾讯tsf·分布式利器:腾讯tsf
故事不长丨3 天前
C#字典(Dictionary)全面解析:从基础用法到实战优化
开发语言·c#·wpf·哈希算法·字典·dictionary·键值对