0

我尝试创建一个简单的十六进制输入控件。在这个控件中,当用户编辑时,应该在 2 个字符之后添加一个空格字符。不应强迫用户按空格键,应自动添加空格。空格字符不应该在绑定值中。十六进制字符串也不应该有固定的长度(就像带有掩码的文本框一样)。

是否有可用的扩展或控件,或者是否有人已经创建了这样的控件?

4

2 回答 2

3

一个简单的解决方案是使用转换器执行此操作:

public class SpaceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string newValue = "";
        int cnt = 0;
        foreach (char c in value.ToString())
        {
            if (cnt == 2)
            {
                 newValue += " ";
                 cnt=0;
            }
            newValue += c;
            cnt++;
        }
        return newValue;
    }

    public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture)
    {
        return value.Tostring().Replace(" ","");
    }
}

编辑:为了设置光标,我创建了一个关注格式的附加属性:

public class TextBoxFormatter
{
    public static readonly DependencyProperty EnableFormattingProperty =
        DependencyProperty.RegisterAttached("EnableFormatting", typeof(bool), typeof(TextBoxFormatter),
            new PropertyMetadata(default(bool), PropertyChangedCallback));

    private static void PropertyChangedCallback(DependencyObject dependencyObject,
        DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        TextBox tb = dependencyObject as TextBox;
        if (tb != null)
        {
            bool value = (bool)dependencyPropertyChangedEventArgs.NewValue;
            tb.TextChanged -= TBTextChanged;
            if (value)
            {
                Format(tb, true);
                tb.TextChanged += TBTextChanged;
            }
        }
    }

    public static void SetEnableFormatting(TextBox element, bool value)
    {
        element.SetValue(EnableFormattingProperty, value);
    }

    public static bool GetEnableFormatting(TextBox element)
    {
        return (bool) element.GetValue(EnableFormattingProperty);
    }

    private static void TBTextChanged(object sender, TextChangedEventArgs e)
    {
        Format(sender as TextBox);
    }

    private static void Format(TextBox tb, bool init = false)
    {
        if (tb != null)
        {
            int ci = tb.CaretIndex;
            string newValue = "";
            int cnt = 0;
            foreach (char c in tb.Text)
            {
                if (c != ' ')
                {
                    if (cnt > 0 && ShouldFormat(cnt))
                    {
                        newValue += " ";
                        if (ci > cnt && init)
                            ci++;
                    }
                    cnt++;
                    newValue += c;
                }
            }
            tb.Text = newValue;
            SetCaret(tb, ci);
        }
    }

    private static void SetCaret(TextBox tb, int oldCaret)
    {
        if (oldCaret <= 0 || oldCaret >= tb.Text.Length)
            return;

        if (tb.Text[oldCaret-1] != ' ' && tb.Text[oldCaret] != ' ')
            tb.CaretIndex += oldCaret;
        else
            tb.CaretIndex = oldCaret+1;
    }

    private static bool ShouldFormat(int index)
    {
        return index%2 == 0;
    }
}

如何使用它:

<TextBox ns:TextBoxFormatter.EnableFormatting="True"></TextBox>
于 2013-09-23T09:28:21.643 回答
0

您可以通过覆盖它的OnTextChanged方法来实现自己的控制

public class HexTextBox : TextBox
{
    private bool isUserTextChaned = true;

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        if (isUserTextChaned)
        {
            isUserTextChaned = false;

            string temp = Text.Replace(" ", string.Empty);

            // Support for backspace
            if (e.Changes.First().RemovedLength > 0 && !Text.EndsWith(" "))
            {
                temp = temp.Substring(0, temp.Length - e.Changes.First().RemovedLength);
            }

            // Insert spaces
            temp = Regex.Replace(temp, @"(.{2})", "$1 ");

            // Update text
            Text = temp;

            isUserTextChaned = true;

            // Set cursor
            Select(Text.Length, Text.Length);

            base.OnTextChanged(e);
        }
    }
}

解释:

由于对Text属性的每次更改都会触发TextChanged事件,为了避免递归,我添加了isUserTextChanged字段以确定 是从TextChanged外部触发的。

接下来,我们每隔三个字符重新定义一个Text属性,在每两个字符之间添加一个 ' '。

最后,我们Text通过选择最后一个 char将光标设置到末尾Select(Text.Length, Text.Length);

希望这可以帮助 :)

于 2013-09-23T09:20:56.320 回答