Pole numeryczne

0

Cały czas w C# brakowało mi porządnego pola numerycznego. Jakoś w clipperze moglo byc pomimo tego, ze w clipperze niczego nie bylo a w C# nie ma choć jest wszystko ;-)
No wiec napisalem sobie wreszcie obsluge takiego pola.
Problem w tym, ze chcac uniknac kazdorazowego wklejania kodu (badz wywolywania metod) do eventsow przydalby sie wstepnie zdefiniowany taki TextBox. Tyle, ze nie wiem jak się do tego zabrac.
Częściowo wykorzystałem kod z netu. Działa to tak:

  1. można wprowadzic tylko cyfry, przecinek i minus

  2. przecinek i minus moga wystapic tylko raz

  3. minus tylko na poczatku

  4. po wyjsciu z pola wartosc jest zaokraglana do 2 miejsc po przecinku

  5. po wyjsciu sa wstawiane seperatory tysiecy

  6. przy wejsciu seperatory tysiecy sa usuwane
    Poniżej kod obsługujący pole numeryczne:

    using System.Globalization;
    using System.Text.RegularExpressions;

     private void NominalTextBox_KeyPress(object sender, KeyPressEventArgs e)
     {
         string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
         string negativeSign = numberFormatInfo.NegativeSign;
         string keyInput = e.KeyChar.ToString();
    
         if (Char.IsDigit(e.KeyChar))
         {
             // digit is OK
         }
         else if (keyInput.Equals(decimalSeparator) || keyInput.Equals(negativeSign))
         {
             // Decimal separator is OK
             if (keyInput.Equals(decimalSeparator) & ((TextBox)sender).Text.IndexOf(decimalSeparator) != (-1))
             {
                 e.Handled = true; // przecinek moze wystapic tylko raz
             }
             else if (keyInput.Equals(negativeSign) & ((TextBox)sender).Text.IndexOf(negativeSign) != (-1))
             {
                 e.Handled = true; // minus moze wystapic tylko raz
             }
             else if (keyInput.Equals(negativeSign) & ((TextBox)sender).SelectionStart != 0)
             {
                 e.Handled = true; // minus moze byc tylko na poczatku
             }
    
         }
         else if (e.KeyChar == '\b')
         {
             // Backspace key is OK
         }
         //    else if ((ModifierKeys & (Keys.Control | Keys.Alt)) != 0)
         //    {
         //     // Let the edit control handle control and alt key combinations
         //    }
         else
         {
             // Consume this invalid key and beep
             e.Handled = true;
             //    MessageBeep();
         }
    
     }
    
     private void NominalTextBox_Leave(object sender, EventArgs e)
     {
         string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
         string groupSeparator = numberFormatInfo.NumberGroupSeparator;
    
       ((TextBox)sender).Text = decimal.Round(decimal.Parse(((TextBox)sender).Text), 2).ToString();
       int pozycjaPrzecinka = ((TextBox)sender).Text.IndexOf(decimalSeparator);
         if (pozycjaPrzecinka==(-1)) 
             ((TextBox)sender).Text = ((TextBox)sender).Text + decimalSeparator + "00";
         else if ((((TextBox)sender).Text.Length) - pozycjaPrzecinka == 2)
             ((TextBox)sender).Text = ((TextBox)sender).Text + "0";
         string numberMask="";
         int seperator = 6;
         for (int i = 0; i <= ((TextBox)sender).Text.Length - 1; i++)
         {
             numberMask = ((TextBox)sender).Text.Substring(((TextBox)sender).Text.Length - i - 1, 1) + numberMask;
             if (numberMask.Length == seperator)
             {
                 numberMask = groupSeparator + numberMask;
                 seperator = seperator + 4;
             }
    
         }
         ((TextBox)sender).Text = numberMask.Trim();
     }
    
    
     private void NominalTextBox_Enter(object sender, EventArgs e)
     {
         ((TextBox)sender).Text=Regex.Replace(((TextBox)sender).Text, @"\s", "");
     }
    
</ol>
0

Przenioslem kod do metod statycznych i obsluga juz jest nieco latwiejsza ale nie wiem czy nie mozna tego jeszcze lepiej zrobic.

private void NominalTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
Pomocne.PoleNumeryczne.PoleNumeryczne_KeyPress(sender, e);
}

    private void NominalTextBox_Leave(object sender, EventArgs e)
    {
        Pomocne.PoleNumeryczne.PoleNumeryczne_Leave(sender, e);
    }

    private void NominalTextBox_Enter(object sender, EventArgs e)
    {
        Pomocne.PoleNumeryczne.PoleNumeryczne__Enter(sender, e);
    }
0

w tej wersji nie mozna wpisac cyfry przed minusem i moze zaokraglac do dowolnej ilosci liczb po przecinku.
Tylko caly czas pozostaje główny problem jak to wygodnie powiązać z TextBox'em

class PoleNumeryczne
{
private static NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
public static void PoleNumeryczne_KeyPress(object sender, KeyPressEventArgs e)
{
string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
string negativeSign = numberFormatInfo.NegativeSign;
string keyInput = e.KeyChar.ToString();

        if (Char.IsDigit(e.KeyChar))
        {
            // digit is OK
            if (((TextBox)sender).Text.IndexOf(negativeSign) !=(-1) & ((TextBox)sender).SelectionStart==0)
            {
                e.Handled = true; // nie mozna wstawiac znakow przed minusem
            }

        }
        else if (keyInput.Equals(decimalSeparator) || keyInput.Equals(negativeSign))
        {
            // Decimal separator is OK
            if (keyInput.Equals(decimalSeparator) & ((TextBox)sender).Text.IndexOf(decimalSeparator) != (-1))
            {
                e.Handled = true; // przecinek moze wystapic tylko raz
            }
            else if (keyInput.Equals(negativeSign) & ((TextBox)sender).Text.IndexOf(negativeSign) != (-1))
            {
                e.Handled = true; // minus moze wystapic tylko raz
            }
            else if (keyInput.Equals(negativeSign) & ((TextBox)sender).SelectionStart != 0)
            {
                e.Handled = true; // minus moze byc tylko na poczatku
            }

        }
        else if (e.KeyChar == '\b')
        {
            // Backspace key is OK
        }
        //    else if ((ModifierKeys & (Keys.Control | Keys.Alt)) != 0)
        //    {
        //     // Let the edit control handle control and alt key combinations
        //    }
        else
        {
            // Consume this invalid key and beep
            e.Handled = true;
            //    MessageBeep();
        }

    }

    public static void PoleNumeryczne_Leave(object sender, EventArgs e, int iloscPoPrzecinku)
    {
        string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
        string groupSeparator = numberFormatInfo.NumberGroupSeparator;

        ((TextBox)sender).Text = decimal.Round(decimal.Parse(((TextBox)sender).Text), iloscPoPrzecinku).ToString();
      int pozycjaPrzecinka = ((TextBox)sender).Text.IndexOf(decimalSeparator);
      StringBuilder stringBuilder = new StringBuilder();
        int iloscZnakowPoPrzecinku=(((TextBox)sender).Text.Length) - pozycjaPrzecinka-1;
      if (pozycjaPrzecinka == (-1))
      {
          ((TextBox)sender).Text = ((TextBox)sender).Text + decimalSeparator;   
          stringBuilder.Append(Convert.ToChar("0"), iloscPoPrzecinku);
          ((TextBox)sender).Text = ((TextBox)sender).Text + stringBuilder.ToString();
      }
      else if (iloscZnakowPoPrzecinku != iloscPoPrzecinku)
      {
          stringBuilder.Append(Convert.ToChar("0"), iloscPoPrzecinku-iloscZnakowPoPrzecinku);
          ((TextBox)sender).Text = ((TextBox)sender).Text + stringBuilder.ToString();
      }
        string numberMask="";
        int seperator = iloscPoPrzecinku+4;
        for (int i = 0; i <= ((TextBox)sender).Text.Length -1; i++)
        {
            numberMask = ((TextBox)sender).Text.Substring(((TextBox)sender).Text.Length - i -1, 1) + numberMask;
            if (numberMask.Length == seperator)
            {
                numberMask = groupSeparator + numberMask;
                seperator = seperator + 4;
            }

        }
        ((TextBox)sender).Text = numberMask.Trim();
    }

    public static void PoleNumeryczne__Enter(object sender, EventArgs e)
    {
        ((TextBox)sender).Text=Regex.Replace(((TextBox)sender).Text, @"\s", "");
    }
}
0

napisz sobie własną kontrolkę dziedziczącą po TB

0

O Dzieki. Własnie z tym walcze. Kontrolka juz jest tylko mi sie eventy nie odpalaja.

Pozdrawiam,
Zoritt

0

No i dziala. super!
Dokładnie o to mi chodzilo.
Specjalne podziekowania dla Misiekd :-)

Pozdrawiam,
Zoritt

0

Dla porządku wkleje jeszcze początek kodu kontrolki, może sie komuś przyda.
A w ogole fajne to C# ;-)

public partial class TextBoxNumeric : TextBox { private static NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat; private int _iloscPoPrzecinku; public TextBoxNumeric() { InitializeComponent(); this.TextAlign = HorizontalAlignment.Right; this.KeyPress += new KeyPressEventHandler(this.PoleNumeryczne_KeyPress); this.Enter += new System.EventHandler(this.PoleNumeryczne_Enter); this.Leave += new System.EventHandler(this.PoleNumeryczne_Leave); } [Description("Ilość po przecinku"), Category("Behavior"), Browsable(true), DefaultValue(2)] public int iloscPoPrzecinku { get { return _iloscPoPrzecinku; } set { _iloscPoPrzecinku = value; } }
0

Chyba ostateczne wersja. Dodane:

  1. Mozna zdefiniować max i nim
  2. Nie wywala sie przy pustym polu
  3. Przy edycji liczby ze znakiem ujemnym poprawnie reaguje na zaznaczenie (select)
  4. Obsługuje pola bez części ułamkowej
    Max, min i ilość znaków po przecinku ustawia sie w propertach kontrolki w czesci "behavior"
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using System.Globalization; using System.Text.RegularExpressions;

namespace SBD.Pomocne
{
public partial class TextBoxNumeric : TextBox
{
private static NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
private int _iloscPoPrzecinku = 2;
private int _zakresPlus = (-1);
private int _zakresMinus = 1;

    public TextBoxNumeric()
    {
        InitializeComponent();
        this.TextAlign = HorizontalAlignment.Right;
        this.KeyPress += new KeyPressEventHandler(this.PoleNumeryczne_KeyPress);
        this.Enter += new System.EventHandler(this.PoleNumeryczne_Enter);
        this.Leave += new System.EventHandler(this.PoleNumeryczne_Leave);
    }

    [System.ComponentModel.Description("Ilość znaków po przecinku"),
    System.ComponentModel.DisplayName("Po przecinku"),
    System.ComponentModel.Category("Behavior"),
    System.ComponentModel.Browsable(true),
    System.ComponentModel.DefaultValue(2)]
    public int iloscPoPrzecinku
    {
        get
        {
            return _iloscPoPrzecinku;
        }
        set
        {
            _iloscPoPrzecinku = value;
        }
    }

    [System.ComponentModel.Description("Max wartość. (-1) brak zakresu"),
    System.ComponentModel.DisplayName("Max wartość"),
    System.ComponentModel.Category("Behavior"),
    System.ComponentModel.Browsable(true),
    System.ComponentModel.DefaultValue(-1)]
    public int zakresPlus
    {
        get
        {
            return _zakresPlus;
        }
        set
        {
            _zakresPlus = value;
        }
    }

    [System.ComponentModel.Description("Min wartość. 1 - brak zakresu"),
    System.ComponentModel.DisplayName("Min wartość"),
    System.ComponentModel.Category("Behavior"),
    System.ComponentModel.Browsable(true),
    System.ComponentModel.DefaultValue(1)]
    public int zakresMinus
    {
        get
        {
            return _zakresMinus;
        }
        set
        {
            _zakresMinus = value;
        }
    }



    public void PoleNumeryczne_KeyPress(object sender, KeyPressEventArgs e)
    {
        string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
        string negativeSign = numberFormatInfo.NegativeSign;
        string keyInput = e.KeyChar.ToString();

        if (Char.IsDigit(e.KeyChar))
        {
            // digit is OK
            if (((TextBox)sender).Text.IndexOf(negativeSign) !=(-1) & ((TextBox)sender).SelectionStart==0
                & ((TextBox)sender).SelectedText.Length == 0)
            {
                e.Handled = true; // nie mozna wstawiac znakow przed minusem chyba ze jest zaznaczony
            }

        }
        else if (keyInput.Equals(decimalSeparator) || keyInput.Equals(negativeSign))
        {
            if (keyInput.Equals(decimalSeparator) & _iloscPoPrzecinku == 0)
            {
                e.Handled = true; // przy polu calkowitym nie moze sie pojawic przecinek
            }
            else if (keyInput.Equals(decimalSeparator) & ((TextBox)sender).Text.IndexOf(decimalSeparator) != (-1))
            {
                e.Handled = true; // przecinek moze wystapic tylko raz
            }
            else if (keyInput.Equals(negativeSign) & ((TextBox)sender).Text.IndexOf(negativeSign) != (-1))
            {
                e.Handled = true; // minus moze wystapic tylko raz
            }
            else if (keyInput.Equals(negativeSign) & ((TextBox)sender).SelectionStart != 0)
            {
                e.Handled = true; // minus moze byc tylko na poczatku
            }

        }
        else if (e.KeyChar == '\b')
        {
            // Backspace key is OK
        }
        //    else if ((ModifierKeys & (Keys.Control | Keys.Alt)) != 0)
        //    {
        //     // Let the edit control handle control and alt key combinations
        //    }
        else
        {
            // Consume this invalid key and beep
            e.Handled = true;
            //    MessageBeep();
        }

    }

    public void PoleNumeryczne_Leave(object sender, EventArgs e)
    {
        string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
        string groupSeparator = numberFormatInfo.NumberGroupSeparator;
        if (((TextBox)sender).Text == "")
        {
            ((TextBox)sender).Text = "0";
        }
        decimal wartoscNumeryczna = decimal.Round(decimal.Parse(((TextBox)sender).Text), _iloscPoPrzecinku);
        ((TextBox)sender).Text = wartoscNumeryczna.ToString();
      int pozycjaPrzecinka = ((TextBox)sender).Text.IndexOf(decimalSeparator);
      if (_zakresPlus != (-1))
      {
          if (_zakresPlus < wartoscNumeryczna)
          {
              MessageBox.Show("Wartość pola nie może przekraczać: " + _zakresPlus.ToString(), "SBD", MessageBoxButtons.OK, MessageBoxIcon.Stop);
              ((TextBox)sender).Focus();
          }
      }
      if (_zakresMinus != (1))
      {
          if (_zakresMinus > wartoscNumeryczna)
          {
              MessageBox.Show("Wartość pola nie może być mniejsza od: " + _zakresMinus.ToString(), "SBD", MessageBoxButtons.OK, MessageBoxIcon.Stop);
              ((TextBox)sender).Focus();
          }
      }

      StringBuilder stringBuilder = new StringBuilder();
        int iloscZnakowPoPrzecinku=(((TextBox)sender).Text.Length) - pozycjaPrzecinka-1;
        if (_iloscPoPrzecinku == 0)
        {
            //to nie rob nic
        }
      else if (pozycjaPrzecinka == (-1))
      {
          ((TextBox)sender).Text = ((TextBox)sender).Text + decimalSeparator;   
          stringBuilder.Append(Convert.ToChar("0"), _iloscPoPrzecinku);
          ((TextBox)sender).Text = ((TextBox)sender).Text + stringBuilder.ToString();
      }
      else if (iloscZnakowPoPrzecinku != _iloscPoPrzecinku)
      {
          stringBuilder.Append(Convert.ToChar("0"), _iloscPoPrzecinku-iloscZnakowPoPrzecinku);
          ((TextBox)sender).Text = ((TextBox)sender).Text + stringBuilder.ToString();
      }
        string numberMask="";
        int seperator = _iloscPoPrzecinku+4;
        for (int i = 0; i <= ((TextBox)sender).Text.Length -1; i++)
        {
            numberMask = ((TextBox)sender).Text.Substring(((TextBox)sender).Text.Length - i -1, 1) + numberMask;
            if (numberMask.Length == seperator)
            {
                numberMask = groupSeparator + numberMask;
                seperator = seperator + 4;
            }

        }
        ((TextBox)sender).Text = numberMask.Trim();
    }

    public void PoleNumeryczne_Enter(object sender, EventArgs e)
    {
        ((TextBox)sender).Text = Regex.Replace(((TextBox)sender).Text, @"\s", "");
    }
}

}

0

wszystko ok ale zamiast podpinać się pod zdarzenia powinieneś nadpisać metody, które je wywołują

np zamiast
this.KeyPress += new KeyPressEventHandler(this.PoleNumeryczne_KeyPress);

powinieneś dać
<code class="c#">protected override void OnKeyPress(KeyPressEventArgs e)
{
    base.OnKeyPress(e);
    //i tutaj wstawić to co masz w PoleNumeryczne_KeyPress
}

to jest właśnie cała idea obiektowości - masz klasę, którą chcesz rozszerzyć to po prostu dziedziczysz po niej i nadpisujesz metody, które chcesz zmienić

0

Chetnie ... ale cos nie tak.
Nie moge przykryc KeyPress poniewaz to jest event a nie metoda. W kazdym badz razie glupi kompilator cos mi tutaj marudzi ;-)
Jest tez druga mozliwosc, ze czegos nie rozumiem ...

ps. A tak przy okazji pozdrowienia
dla Dąbrowy Górniczej! To moje ulubione miasto :-)

Pozdrawiam,
Zoritt

1 użytkowników online, w tym zalogowanych: 0, gości: 1