wpf TextBox 应以特定格式以十六进制显示文本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12619165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
TextBox should display text in hexadecimal in a specific format
提问by Owais Wani
I have a textbox in my xaml file which is editable. Now according to my project requirements content in textbox should only be 0-9 and a-f (hexadecimal values) and textbox should take the input based on hexadecimal values.
我的 xaml 文件中有一个可编辑的文本框。现在根据我的项目要求,文本框中的内容应该只有 0-9 和 af(十六进制值),文本框应该基于十六进制值进行输入。
Demonstratation:
演示:
12 ab 32 a5 64
12 ab 32 a5 64
Now if my cursor is at the end and i go on pressing backspace, it shud remove the values as it happens in a general text box.
现在,如果我的光标在末尾并且我继续按退格键,它会删除常规文本框中发生的值。
Now If my cursor is at the beginning of a5, and i press "delete key", the value should become like:
现在,如果我的光标位于 a5 的开头,并且我按“删除键”,则该值应变为:
12 ab 32 56 4
12 AB 32 56 4
If my cursor is at the end of a5 and i press the 'delete key" nothing should happen.
如果我的光标位于 a5 的末尾并且我按下“删除键”,则不会发生任何事情。
I had done this successful in my C++ application as follows:
我在我的 C++ 应用程序中成功地做到了这一点,如下所示:
void CMSP430CommPanel::textEditorTextChanged (TextEditor& editor)
{
if(&editor == m_texti2cWrite)
{
int count = 0;
int location;
String text1 = m_texti2cWrite->getText();
String text = m_texti2cWrite->getText().removeCharacters(" ");
String hexString = String::empty;
int countCaret = m_texti2cWrite->getCaretPosition();
for(int i=0; i < text.length(); i++)
{
hexString = hexString + String (&text[i], 1);
if((i+1) % 2 == 0)
{
if(i != text.length()-1)
{
hexString = hexString + T(" ");
count ++;
}
}
count ++;
}
m_texti2cWrite->setText(hexString,false);
if(text1.length() == m_texti2cWrite->getCaretPosition())
{
m_texti2cWrite->setCaretPosition(count);
}
else
{
m_texti2cWrite->setCaretPosition(countCaret);
}
}
}
}
where m_texti2cWrite is the name given to textbox. How can i implement the same case in my wpf application which is MVVM based. I have a textbox which shud take inputs as I said above. please help!!!
其中 m_texti2cWrite 是给文本框的名称。我如何在基于 MVVM 的 wpf 应用程序中实现相同的案例。我有一个文本框,正如我上面所说的,它可以接受输入。请帮忙!!!
回答by Richard Friend
Since you are using MVVM - you could do this via a Value Converter- i had a go at doing this, mostly out of curiosity - this seems to work quite well but currently requires an instance of the convertor per control as it is using an instance variable to cache the last known good hex value - im sure you could use it in conjunction with validation to improve it.
由于您使用的是 MVVM - 您可以通过值转换器来执行此操作- 我尝试这样做,主要是出于好奇 - 这似乎工作得很好,但目前每个控件都需要一个转换器实例,因为它正在使用一个实例变量来缓存最后一个已知的良好十六进制值 - 我相信你可以将它与验证结合使用来改进它。
UpdateOkay this seems to work(ish) - allows only 1-9 & A-F, i have had to disable textbox selection as it was causing strange results - i have used an attached behaviour to control the cursor, there may be a better way to do this but i sure dont know how...
更新好吧,这似乎有效(ish)-仅允许 1-9 和 AF,我不得不禁用文本框选择,因为它会导致奇怪的结果-我使用附加行为来控制光标,可能有更好的方法这样做,但我肯定不知道如何...
The delete behaviour works as you asked (if you delete at the end of a pair it does nothing).
删除行为按您的要求工作(如果您在一对末尾删除它什么都不做)。
Have a play :)
有戏:)
Update 2
更新 2
Made some changes to get it to work with text selection.
进行了一些更改以使其与文本选择一起使用。
View
看法
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<local:HexStringConverter x:Key="HexConverter"></local:HexStringConverter>
</Grid.Resources>
<StackPanel>
<TextBox local:TextBoxBehaviour.KeepCursorPosition="true" VerticalAlignment="Center" Width="200" HorizontalAlignment="Center" Text="{Binding HexValue,Mode=TwoWay,Converter={StaticResource HexConverter},UpdateSourceTrigger=PropertyChanged}"></TextBox>
</StackPanel>
</Grid>
View code behind
查看后面的代码
public partial class MainWindow : Window
{
public MainWindow()
{
this.DataContext = new MyViewModel();
InitializeComponent();
}
ViewModel
视图模型
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
private string hexValue;
public string HexValue
{
get
{
return hexValue;
}
set
{
hexValue = value;
OnPropertyChanged("HexValue");
}
}
}
Hex Converter
十六进制转换器
public class HexStringConverter : IValueConverter
{
private string lastValidValue;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string ret = null;
if (value != null && value is string)
{
var valueAsString = (string)value;
var parts = valueAsString.ToCharArray();
var formatted = parts.Select((p,i)=>(++i)%2==0 ? String.Concat(p.ToString()," ") : p.ToString());
ret = String.Join(String.Empty,formatted).Trim();
}
return ret;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
object ret = null;
if (value != null && value is string)
{
var valueAsString = ((string)value).Replace(" ",String.Empty).ToUpper();
ret = lastValidValue = IsHex(valueAsString) ? valueAsString : lastValidValue;
}
return ret;
}
private bool IsHex(string text)
{
var reg = new System.Text.RegularExpressions.Regex("^[0-9A-Fa-f]*$");
return reg.IsMatch(text);
}
}
Textbox behaviour
文本框行为
public static class TextBoxBehaviour
{
public static bool GetKeepCursorPosition(DependencyObject obj)
{
return (bool)obj.GetValue(KeepCursorPositionProperty);
}
public static void SetKeepCursorPosition(DependencyObject obj, bool value)
{
obj.SetValue(KeepCursorPositionProperty, value);
}
// Using a DependencyProperty as the backing store for KeepCursorPosition. This enables animation, styling, binding, etc...
public static readonly DependencyProperty KeepCursorPositionProperty =
DependencyProperty.RegisterAttached("KeepCursorPosition", typeof(bool), typeof(TextBoxBehaviour), new UIPropertyMetadata(false, KeepCursorPosition));
public static int GetPreviousCaretIndex(DependencyObject obj)
{
return (int)obj.GetValue(PreviousCaretIndexProperty);
}
public static void SetPreviousCaretIndex(DependencyObject obj, int value)
{
obj.SetValue(PreviousCaretIndexProperty, value);
}
// Using a DependencyProperty as the backing store for PreviousCaretIndex. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PreviousCaretIndexProperty =
DependencyProperty.RegisterAttached("PreviousCaretIndex", typeof(int), typeof(TextBoxBehaviour), new UIPropertyMetadata(0));
public static string GetPreviousTextValue(DependencyObject obj)
{
return (string)obj.GetValue(PreviousTextValueProperty);
}
public static void SetPreviousTextValue(DependencyObject obj, string value)
{
obj.SetValue(PreviousTextValueProperty, value);
}
// Using a DependencyProperty as the backing store for PreviousTextValue. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PreviousTextValueProperty =
DependencyProperty.RegisterAttached("PreviousTextValue", typeof(string), typeof(TextBoxBehaviour), new UIPropertyMetadata(null));
private static void KeepCursorPosition(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var textBox = sender as TextBox;
if (textBox != null)
{
textBox.PreviewKeyDown += new System.Windows.Input.KeyEventHandler(textBox_PreviewKeyDown);
textBox.TextChanged += new TextChangedEventHandler(textBox_TextChanged);
textBox.Unloaded += new RoutedEventHandler(textBox_Unloaded);
}
else
{
throw new ArgumentException("KeepCursorPosition only available for textboxes");
}
}
static void textBox_Unloaded(object sender, RoutedEventArgs e)
{
var textBox = sender as TextBox;
textBox.PreviewKeyDown -= new System.Windows.Input.KeyEventHandler(textBox_PreviewKeyDown);
textBox.TextChanged -= new TextChangedEventHandler(textBox_TextChanged);
textBox.Unloaded -= new RoutedEventHandler(textBox_Unloaded);
}
static void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
//For some reason our e.Changes only ever contains 1 change of 1 character even if our
//converter converts it to 2 chars with the additional space - hmmm?
var textBox = sender as TextBox;
var previousIndex = GetPreviousCaretIndex(textBox);
var previousText = GetPreviousTextValue(textBox);
var previousLen = !String.IsNullOrEmpty(previousText) ? previousText.Length : 0;
var currentLen = textBox.Text.Length;
var change = (currentLen - previousLen);
var newCharIndex = Math.Max(1, (previousIndex + change));
Debug.WriteLine("Text Changed Previous Caret Pos : {0}", previousIndex);
Debug.WriteLine("Text Changed Change : {0}", change);
Debug.WriteLine("Text Changed New Caret Pos : {0}", newCharIndex);
textBox.CaretIndex = Math.Max(newCharIndex, previousIndex);
SetPreviousCaretIndex(textBox, textBox.CaretIndex);
SetPreviousTextValue(textBox, textBox.Text);
}
static void textBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
var textBox = sender as TextBox;
Debug.WriteLine("Key Preview Caret Pos : {0}", textBox.CaretIndex);
Debug.WriteLine("------------------------");
SetPreviousCaretIndex(textBox, textBox.CaretIndex);
SetPreviousTextValue(textBox, textBox.Text);
}
}
回答by Dennis
Try to use MaskedTextBoxfrom Extended WPF Toolkit.Sorry, I've looked more attentively to possible mask values in MaskedTextBox. There's no mask chars for hex numbers. :(
尝试使用Extended WPF Toolkit 中的MaskedTextBox。抱歉,我更仔细地查看了MaskedTextBox. 十六进制数字没有掩码字符。:(
You should un-mark the answer.
I've posted an issueat Extended WPF Toolkit's tracker.
您应该取消标记答案。
我在扩展 WPF 工具包的跟踪器上发布了一个问题。

