How to make Custom TextBox that wouldn't override the style in WPF .XAML

1k Views Asked by At

So, I made a Custom TextBox, that would only allow numbers:

public partial class IntegerTextBox : TextBox
{
    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        base.OnTextChanged(e);

        Text = new String(Text.Where(c => Char.IsDigit(c)).ToArray());
        SelectionStart = Text.Length;
    }
}

The problem I'm facing is that when I create it ether this way

IntegerTextBox textBox = new IntegerTextBox() {... };

Or

<u:IntegerTextBox/>

in my .xaml

It also overrides the default style used by the environment that I'm working at (Milestone Systems). So instead of getting grey TextBoxes that I should get, I get Windows Default white TextBox.

In the Microsoft documentation, I found a similar example with the explanation, but I can't really seem to find a way to make it work: override example

protected override void OnPaint(PaintEventArgs pe)
{
   base.OnPaint(pe);
   // Insert code to do custom painting.
   // If you want to completely change the appearance of your control,
   // do not call base.OnPaint(pe).
}

As far as I understand, it says: don't call the

base.OnTextChanged(e);

(in my case) if you don't want to change the appearance of the control. I tried removing it and got the same results.

3

There are 3 best solutions below

0
mm8 On BEST ANSWER

Define an implicit Style for your IntegerTextBox in App.xaml:

<Style TargetType="{x:Type local:IntegerTextBox}" BasedOn="{StaticResource {x:Type TextBox}}">

Then it should inherit any implicit Style that is currently applied to <TextBox /> elements.

0
Drreamer On

The problem likely occurs because the new IntegerTextBox class does not use style used by the base TextBox class. Please refer to the following thread where a similar problem was already discussed: https://stackoverflow.com/a/6780802/12797700

0
Null On

If you don't want to re-style the TextBox then you don't even need to create a custom TextBox, instead all you need is "Attached Property".

In your project (UI project if it is MVVM) create a class like using the content below:

public class TextBoxExtensions
    {

        public static readonly DependencyProperty OnlyNumbersAllowedProperty =
            DependencyProperty.Register("OnlyNumbersAllowed", typeof(int), typeof(TextBoxExtensions), new PropertyMetadata(false,
                (o, args) =>
                {
                    // Assuring we are dealing with TextBox.
                    if (!(o is TextBox textField))
                        return;

                    // make sure TextBox contains characters.
                    if (textField.Text.Length == 0)
                        return;

                    // if TextBox only contains numbers then we are fine and don't go any further.
                    if (textField.Text.All(char.IsDigit)) return;

                    // A letter has been written in TextBox so that we remove it.
                    var result = textField.Text.Remove(textField.Text.Length - 1, 1);
                    textField.Text = result;


                }));

        public static bool GetOnlyNumberSupported(DependencyObject obj)
        {
            return (bool)obj.GetValue(OnlyNumbersAllowedProperty);
        }

        public static void SetOnlyNumberSupported(DependencyObject obj, bool value)
        {
            obj.SetValue(OnlyNumbersAllowedProperty, value);
        }

    }

Now you can use it anywhere (For Only TextBoxes) inside your views, like this:

local:TextBoxExtensions.OnlyNumbersAllowed="True"

Hint: local is a path to the location of above class inside your project which can be declare via "xmlns".