-1

I have a code from WinForms that, when pressing a key on a textbox, checks which character is entered and if it is a dot, then it changes to a comma, and if it is something else, then it is checked whether it is a digit or not

private void textbox_KeyPress(object sender, KeyPressEventArgs e)
    {
        char ch = e.KeyChar;
        if (ch == '.')
        {
            e.KeyChar = ',';
        }
        if ((!Char.IsDigit(ch)) && (ch != ',') && (ch != '.') && (ch != 8))
        {
            e.Handled = true;
        }
    }

How do I implement such code on WPF

Now the code is like this:

<TextBox 
        PreviewTextInput="NumberValidationTextBox"
        />

private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
    {
        Regex regex = new Regex("[^0-9,.]+");
        e.Handled = regex.IsMatch(e.Text);
    }

In the TextBox, you can now enter numbers, a dot and a comma, it remains only to change the dot to a comma, as an option to use the textchanged event, but since I need this event for another code where the dots will already be changed to commas, then using this event is not an option.

  • There are a lot of ways to do what you are asking, depending on what your use case is. Can you post what you have tried so far? – Ibrennan208 Jun 05 '22 at 19:31
  • What value of `e.Key` will be equal to a point and what value will be equal to a comma? – xXKoksMenXx Jun 05 '22 at 20:16
  • I'm not sure what you mean. Can you post what you have tried so far in WPF so we can see how it compares to your Winforms code? – Ibrennan208 Jun 05 '22 at 20:23
  • added new code. – xXKoksMenXx Jun 06 '22 at 04:51
  • Well, firstly, there is no KeyPress event in WPF, and secondly, it works crookedly, a dot is put, then when you click on another dot, the text input is moved to the beginning, the dot changes to a comma, but a new one is put @Ibrennan208 – xXKoksMenXx Jun 06 '22 at 06:16
  • There is also a code that changes a dot to a comma, but together with other code it does not work correctly ```Regex regex = new Regex(","); if (regex.IsMatch(e.Text)) { e.Handled = true; testTexBox.Text += "."; testTexBox.CaretIndex = testTexBox.Text.Length; }``` – xXKoksMenXx Jun 06 '22 at 06:18
  • sorry, I had copied the wrong method from your code. I fixed that. If you are looking for a KeyPress event, there is a KeyDown you can subscribe to as well. – Ibrennan208 Jun 06 '22 at 06:29
  • Thanks a lot, by trial and error, I made a working code @Ibrennan208 – xXKoksMenXx Jun 06 '22 at 06:44
  • Another question is, how can I accept my answer as correct if he writes to me that I can accept it within two days? @Ibrennan208 – xXKoksMenXx Jun 06 '22 at 06:45
  • The problem is relevant again, I don't know why, but now there are only commas, although everything worked correctly before restarting the project @Ibrennan208 – xXKoksMenXx Jun 06 '22 at 07:00
  • The problem is clear, if you change the comma to a dot, then everything works correctly, and if vice versa, then – xXKoksMenXx Jun 06 '22 at 07:03

2 Answers2

0

Perhaps you are able to cast the sender as a TextBox and then set the text that way? Like:

    private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
    {
            Regex regex = new Regex("[^0-9,.]+");

            e.Handled = regex.IsMatch(e.Text);


            if (sender is TextBox textbox)
            {


                var currentText = textbox.Text;

                textbox.Text = currentText.Replace('.', ',');
            }
    }

It's difficult to figure out what your intent is here.

You may just want to subscribe to the TextChanged event on your text entry and modify the information as it comes in. Within that method you should be able to update the text to your liking, and confirm that the text is valid.

See Microsoft's documentation here.

Here is an example of how you might do it:

<TextBox TextChanged="Entry_TextChanged"/>
private void Entry_TextChanged(object sender, TextChangedEventArgs e)
{
        //textBox.TextChanged -= Entry_TextChanged;
        //textBox.Text = textBox.Text.Replace(".",".");
        //textBox.TextChanged += Entry_TextChanged;
}

Further research shows Microsoft has documentation on Binding Validation, which I believe will suit your case. You can read more about it here.

Here's an example of how to implement a validation rule in WPF, where the XAML shows the instantiation of the ValidationRule object, and the C# shows how that ValidationRule was implemented:

<TextBox Name="textBox1" Width="50" FontSize="15"
         Validation.ErrorTemplate="{StaticResource validationTemplate}"
         Style="{StaticResource textBoxInError}"
         Grid.Row="1" Grid.Column="1" Margin="2">
  <TextBox.Text>
    <Binding Path="Age" Source="{StaticResource ods}"
             UpdateSourceTrigger="PropertyChanged" >
      <Binding.ValidationRules>
        <c:AgeRangeRule Min="21" Max="130"/>
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>
public class AgeRangeRule : ValidationRule
{
    public int Min { get; set; }
    public int Max { get; set; }

    public AgeRangeRule()
    {
    }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        int age = 0;

        try
        {
            if (((string)value).Length > 0)
                age = Int32.Parse((String)value);
        }
        catch (Exception e)
        {
            return new ValidationResult(false, $"Illegal characters or {e.Message}");
        }

        if ((age < Min) || (age > Max))
        {
            return new ValidationResult(false,
              $"Please enter an age in the range: {Min}-{Max}.");
        }
        return ValidationResult.ValidResult;
    }
}

If that doesn't work, then this answer may be helpful: How do I get a TextBox to only accept numeric input in WPF?

Otherwise, this can also be done by implementing some form of DataTrigger.

A DataTrigger "Represents a trigger that applies property values or performs actions when the bound data meets a specified condition."

See Microsoft's documentation here.

An example pulled from their page shows how you can change the foreground color of a ListBoxItem conditionally, based on the text property of a Place object:

<Window.Resources>
  <c:Places x:Key="PlacesData"/>

  <Style TargetType="ListBoxItem">
    <Style.Triggers>
      <DataTrigger Binding="{Binding Path=State}" Value="WA">
        <Setter Property="Foreground" Value="Red" />
      </DataTrigger>    
      <MultiDataTrigger>
        <MultiDataTrigger.Conditions>
          <Condition Binding="{Binding Path=Name}" Value="Portland" />
          <Condition Binding="{Binding Path=State}" Value="OR" />
        </MultiDataTrigger.Conditions>
        <Setter Property="Background" Value="Cyan" />
      </MultiDataTrigger>
    </Style.Triggers>
  </Style>

  <DataTemplate DataType="{x:Type c:Place}">
    <Canvas Width="160" Height="20">
      <TextBlock FontSize="12"
             Width="130" Canvas.Left="0" Text="{Binding Path=Name}"/>
      <TextBlock FontSize="12" Width="30"
                 Canvas.Left="130" Text="{Binding Path=State}"/>
    </Canvas>
  </DataTemplate>
</Window.Resources>

<StackPanel>
  <TextBlock FontSize="18" Margin="5" FontWeight="Bold"
    HorizontalAlignment="Center">Data Trigger Sample</TextBlock>
  <ListBox Width="180" HorizontalAlignment="Center" Background="Honeydew"
    ItemsSource="{Binding Source={StaticResource PlacesData}}"/>
</StackPanel>

Alternatively (or perhaps additionally), you may need to use some sort of converter with your binding. It's possible to have a string converter that replaces all instances of a character with another character and return the transformed string to a binding. See some of Microsoft's documentation on converters here.

Ibrennan208
  • 1,345
  • 3
  • 14
  • 31
  • And yet I don't understand how to change exactly the entered character – xXKoksMenXx Jun 05 '22 at 19:11
  • I just added a section at the top regarding data validation as well, in case you wanted it to be validated on the user side. However, it seems you want to do the change yourself, so I believe the `DataTrigger` with `Converter` would work best. I will update my answer with more. – Ibrennan208 Jun 05 '22 at 19:13
  • `` When using this method, immediately after entering the dot character, it changes to the input of the subsequent text, does not continue in the same place, but begins from the beginning of the textbox bypassing another written text – xXKoksMenXx Jun 05 '22 at 19:38
  • If you modify the text within your `TextChanged` event, you'll probably have to unsubscribe form the text changed event and then subscribe to the event again once you have changed the text programatically. Updated my code to show pseudocode for it. Beyond that, you'll probably need to write your code and post a new question that is more on topic and contains the code you've tried. Your current question is too vague as there are too many ways to do what you are asking. – Ibrennan208 Jun 05 '22 at 19:40
0

As a result, this code works:

private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
    {
        Regex regex = new Regex("[^0-9,.]+");
        e.Handled = regex.IsMatch(e.Text);
        Regex regex1 = new Regex(",");
        if (regex1.IsMatch(e.Text))
        {
            e.Handled = true;
            tb1.Text += ".";
            tb1.CaretIndex = tb1.Text.Length;
        }
    }