2012-09-27 43 views
0

我在可编辑的xaml文件中有一个文本框。现在根据我的项目要求,文本框中的内容应该只有0-9,并且a-f(十六进制值)和文本框应该基于十六进制值进行输入。TextBox应以特定格式以十六进制显示文本

Demonstratation:

12 AB 32 A5 64

现在,如果我的光标是在年底,我去按Backspace键,它shud因为它在一般的文本框中发生取出值。

现在,如果我的光标是在A5的开始,我按下“删除键”,该值应该变得像:

12 AB 32 56 4

如果我的光标是在A5中结束,我按下“删除键”绝不应发生

我做了这个成功在我的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); 
     } 
} 

}

其中m_texti2cWrite是指定给文本框的名称。我如何在我的基于MVVM的wpf应用程序中实现相同的案例。正如我上面所说,我有一个文本框,它可以阻止输入。请帮忙!!!

回答

0

尝试从Extended WPF Toolkit中使用MaskedTextBox 对不起,我更专注于MaskedTextBox中可能的掩码值。对于十六进制数字没有掩码字符。 :(

你应该由于您使用的MVVM未标出答案
我已经发布了一个issue在扩展WPF工具包的跟踪

+0

我从来没有使用MaskedTextBox中。我必须重写C#中的逻辑还是他们的其他方式? –

+0

@OwaisWani:您必须为“MaskedTextBox”控件设置输入掩码,并将控件的“文本”与数据源的某些属性绑定。其余(输入格式)控件将自行完成。 – Dennis

+0

任何其他的选择? –

3

。 - 你可以通过Value Converter做到这一点 - 我了个去在这样做时,主要是出于好奇 - 这似乎工作得很好,但目前需要每个控制器的转换器的实例,因为它使用实例变量来缓存最近已知的十六进制值 - 确保您可以将它与验证以改进它

更新 好吧,这似乎工作(ish) - 只允许1-9 & AF,我不得不禁用文本框选择,因为它造成了奇怪的结果 - 我用一个附加的行为来控制光标,可能有更好的方法来做到这一点,但我肯定不知道如何...

删除行为工作正如你问(如果你删除在一对结束它什么都不做)。

有一出戏:)

更新2

作了一些修改,让它使用文本选择工作。

查看

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

查看后面的代码

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     this.DataContext = new MyViewModel(); 
     InitializeComponent(); 
    } 

视图模型

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


} 

十六进制转换器

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

文本框的行为

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

真棒理查德。虽然我没有尝试过,但它是否成功地执行了上述问题中提到的所有关键操作? –

+0

嗯,我试过了,它看起来不错 - 比我想象的要好,唯一的另一个问题是删除/在十六进制值的中间输入时的字符位置,如果你输入快速,它有时会跳到最后.. –

+0

嗯首先感谢很多兄弟。我用它的应用程序,它似乎有几个问题,因为你提到。首先,当我从0-9输入数值时,它会在每两个数字之间出现一个间隔,但是在输入第三个数字后光标位置似乎进入折腾状态,从而以混合值结束。其次,它接受来自A-Z的所有字母,两个字母之间没有间隔,因此十六进制格式也没有被注意到。我们如何克服它? :( –

相关问题