SAT
SAT

Reputation: 192

Restrict TextBox input upto particular value without disturbing cursor position

I have a WPF application(MVVM) .I want to restrict user from entering more than specific value in a TextBox. Suppose that value is '100' , then user shouldn't be able to enter 101 etc. I have tried following code.

XAML:

<TextBox Text="{Binding SearchText}" FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}" Name="SearchTextBox"  TextChanged="TextBox_TextChanged"/>

CODE:

 private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (textBox != null && !string.IsNullOrEmpty(textBox.Text))
        {
            int searchIndex = 0;
            int count = 100;
            int.TryParse(textBox.Text, out searchIndex);

            if (textBox != null && !string.IsNullOrEmpty(textBox.Text))
            {
                if (searchIndex > Count)
                {
                    textBox.Text = textBox.Text.Substring(0, textBox.Text.Length - 1);
                }
            }
        }
    }

With this code I am able to restrict user from entering more than particular value. But problem is that when I set text of TextBox, then cursor moves to the first digit. Is there any solution for this?

Upvotes: 1

Views: 487

Answers (4)

SAT
SAT

Reputation: 192

One & two . With the help of these two answers I have solved my problem. I am handling two events PreviewKeyDown & TextChanged.

code:

  private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
            TextBox textBox = sender as TextBox;
            int searchIndex = 0;
            int Count = 100;
            int.TryParse(textBox.Text, out searchIndex);
            if (textBox != null && !string.IsNullOrEmpty(textBox.Text))
            {
                if (searchIndex > Count)
                {
                    textBox.Text = OldValue.ToString();
                    textBox.SelectionStart = start;
                 }
             }
      }

public int OldValue = 0;
public int start = 0;


 private void SearchTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        int.TryParse(textBox.Text, out OldValue);
        start = textBox.SelectionStart;
    }

I am saving oldvalue on PreviewKeyDown event and using it on TextChanged event.

Upvotes: 1

mm8
mm8

Reputation: 169210

You could handle the PreviewTextInput event and set the Handled property of the TextCompositionEventArgs to true whenever the validation fails:

private void SearchTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    TextBox textBox = sender as TextBox;
    if (textBox != null)
    {
        string text = textBox.Text + e.Text;
        if (!string.IsNullOrEmpty(text))
        {
            int searchIndex = 0;
            int count = 100;
            int.TryParse(text, out searchIndex);
            e.Handled = (searchIndex > count);
        }
    }
}

Thanks. You answer has solved my most of the issues. But still if I delete first digit and enter another digit, then the validation fails. Suppose count is 150. I enter 150 & then delete 1 & again enter 1 then textbox will get 501 & validation will fail

Well, the you should probably stick to handling the TextChanged event after all. Try this:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = sender as TextBox;
    if (textBox != null)
    {
        const int count = 100;
        int searchIndex = 0;
        int.TryParse(textBox.Text, out searchIndex);
        if (searchIndex > count)
        {
            var textChange = e.Changes.First();
            if (textChange != null && textChange.AddedLength > 0)
            {
                int caret = textBox.CaretIndex;
                int length = textBox.Text.Length;
                textBox.TextChanged -= TextBox_TextChanged;
                textBox.Text = textBox.Text.Substring(0, textChange.Offset) + textBox.Text.Substring(textChange.Offset + textChange.AddedLength);
                textBox.TextChanged += TextBox_TextChanged;
                textBox.CaretIndex = caret - Math.Abs(textBox.Text.Length - length);
            }
        }
    }
}

Upvotes: 2

tabby
tabby

Reputation: 1918

Try this:

Code

 private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (textBox != null && !string.IsNullOrEmpty(textBox.Text))
        {
            int searchIndex = 0;
            int count = 100;
            int.TryParse(textBox.Text, out searchIndex);

            if (textBox != null && !string.IsNullOrEmpty(textBox.Text))
            {
                if (searchIndex > count)
                {
                    textBox.Text = textBox.Text.Substring(0, textBox.Text.Length - 1);
                    textBox.SelectionStart = textBox.Text.Length;
                    textBox.SelectionLength = 0;
                }
            }
        }
    }

Upvotes: 1

Koby Douek
Koby Douek

Reputation: 16675

You can use SelectionStart and SelectionLength like this:

if (searchIndex > Count)
{
     textBox.Text = textBox.Text.Substring(0, textBox.Text.Length - 1);
     textBox.SelectionStart = textBox.Text.Length -1;
     textBox.SelectionLength = 0;
}

Upvotes: 0

Related Questions