Как сделать Custom TextBox, который бы не перекрывал стиль в WPF .XAML - PullRequest
1 голос
/ 28 апреля 2020

Итак, я создал пользовательский текстовый ящик, который будет позволять только цифры:

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;
    }
}

Проблема, с которой я сталкиваюсь, заключается в том, что при создании этого эфира таким образом

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

Или

<u:IntegerTextBox/>

в моем .xaml

Он также переопределяет стиль по умолчанию, используемый средой, в которой я работаю (Milestone Systems). Таким образом, вместо того, чтобы получать серые текстовые поля, которые я должен получить, я получаю Windows Стандартный белый текстовый ящик.

В документации Microsoft я нашел похожий пример с объяснением, но, похоже, не могу найти способ заставить это работать: пример переопределения

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).
}

Насколько я понимаю, он говорит: не вызывайте

base.OnTextChanged(e);

(в моем случае ) если вы не хотите менять внешний вид элемента управления. Я попытался удалить его и получил те же результаты.

Ответы [ 3 ]

1 голос
/ 28 апреля 2020

Определите неявное Style для вашего IntegerTextBox в App.xaml:

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

Тогда оно должно наследовать любые неявные Style, которые в настоящее время применяются к <TextBox /> элементам.

0 голосов
/ 28 апреля 2020

Если вы не хотите изменять стиль TextBox, вам даже не нужно создавать собственный TextBox, вместо этого все, что вам нужно, это «Attached Property».

В вашем проекте (проект пользовательского интерфейса) если это MVVM) создайте класс, используя содержимое ниже:

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);
        }

    }

Теперь вы можете использовать его где угодно (только для текстовых полей) внутри ваших представлений, например:

local:TextBoxExtensions.OnlyNumbersAllowed="True"

Подсказка: local это путь к расположению вышеупомянутого класса внутри вашего проекта, который может быть объявлен через "xmlns".

0 голосов
/ 28 апреля 2020

Вероятно, проблема возникает из-за того, что новый класс IntegerTextBox не использует стиль, используемый базовым классом TextBox. Пожалуйста, обратитесь к следующей теме, где подобная проблема уже обсуждалась: { ссылка }

...