我尝试创建一个简单的Hex输入控件。在此控件中,在用户编辑时,应在2个字符之后添加空格字符。不应强迫用户按空格键,应自动添加空格。 那么空间字符不应该是绑定值。十六进制字符串也不应该有固定长度(就像使用蒙版文本框一样)。
是否有可用的扩展或控件,或者是否有人已经创建了这样的控件?
答案 0 :(得分: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>
答案 1 :(得分: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
将光标设置为Select(Text.Length, Text.Length);
的末尾。
希望这会有所帮助:)