【问题标题】:How to make Custom TextBox that wouldn't override the style in WPF .XAML如何制作不会覆盖 WPF .XAML 中样式的自定义文本框
【发布时间】:2020-04-28 22:12:15
【问题描述】:

所以,我制作了一个只允许数字的自定义文本框:

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 中

它还覆盖了我正在工作的环境(里程碑系统)使用的默认样式。因此,我得到的不是我应该得到的灰色文本框,而是 Windows 默认的白色文本框。

在 Microsoft 文档中,我找到了一个类似的示例和解释,但我似乎真的找不到让它工作的方法: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).
}

据我了解,它说:不要调用

base.OnTextChanged(e);

(在我的情况下)如果您不想更改控件的外观。我尝试删除它并得到相同的结果。

【问题讨论】:

  • 能否请您显示您的类的构造函数。你会覆盖那里的默认样式吗?

标签: c# wpf milestone


【解决方案1】:

在App.xaml 中为您的IntegerTextBox 定义一个隐式Style:

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

那么它应该继承当前应用于&lt;TextBox /&gt; 元素的任何隐式Style。

【讨论】:

    【解决方案2】:

    如果您不想重新设置 TextBox 的样式,那么您甚至不需要创建自定义 TextBox,而只需要“附加属性”即可。

    在您的项目中(如果是 MVVM,则为 UI 项目)创建一个类,如下所示:

    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”声明。

    【讨论】:

      【解决方案3】:

      出现问题的原因可能是新的 IntegerTextBox 类不使用基础 TextBox 类使用的样式。 请参考以下线程,其中已经讨论了类似的问题: https://stackoverflow.com/a/6780802/12797700

      【讨论】:

        猜你喜欢
        • 2014-07-18
        • 2010-09-26
        • 1970-01-01
        • 2016-02-12
        • 2019-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多