创建用下划线替换空格的WPF TextBox的最佳方法是什么?

时间:2010-10-06 13:41:42

标签: c# wpf textbox wpf-controls

我在WPF中创建了一个FilteredTextBox,它包含了所包含的TextBox控件的子类。 FilteredTextBox必须只允许输入[a-zA-Z0-9_]范围内的字符,而且我已经完成了那部分工作。我已经连接到OnPreviewTextInput来处理类型字符,OnPreviewDrop来过滤被拖放的字符,并且我添加了一个PreviewExecutedHandler,它在控件上执行命令时运行以处理粘贴。

到目前为止,非常好。

棘手的部分是控件还应该在输入时用下划线替换空格。

我已经提出了一个解决方案,但它感觉很混乱,我不知道它缺少什么。我觉得必须有一种我不知道的更好的技术。我做了什么:

internal class FilteredTextBox : TextBox
{
    public FilteredTextBox()
    {
        CommandManager.AddPreviewExecutedHandler(this, this.HandlePreviewExecuteHandler);
    }

    private void HandlePreviewExecuteHandler(object sender, ExecutedRoutedEventArgs e)
    {
        var uiCmd = e.Command as RoutedUICommand;
        if (uiCmd != null && (uiCmd.Text == "Space" || uiCmd.Text == "ShiftSpace"))
        {
            // We're manually handling spaces, so we need to make appropriate checks.
            if (this.Text.Length == this.MaxLength) return;

            if (this.SelectionLength == 0)
            {
                // If the user is just typing a space normally
                // We need to cache CaretIndex b/c it's reset to 0 when we set Text.
                var tmpIndex = this.CaretIndex;
                this.Text = this.Text.Insert(tmpIndex, "_");
                this.CaretIndex = tmpIndex + 1;
            }
            else
            {
                // Otherwise, replace the selected text with the underscore and fixup the caret.
                this.SelectedText = "_";
                this.CaretIndex += this.SelectedText.Length;
                this.SelectionLength = 0;
            }

            e.Handled = true; // If someone hits the spacebar, say we handled it.
            return;
        }
    }
}

有更聪明的方法吗?

3 个答案:

答案 0 :(得分:4)

我会将TextBox绑定到ValueConverter,根据需要消除空格,并用下划线替换它们。

ValueConverter看起来像这样:

public class SpaceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return System.Convert.ToString(value); 
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string text = System.Convert.ToString(value);

            //the meat and potatoes is this line
            text = text.Replace(" ", "_");    

            return text;
        }
    }

你的TextBox会以这种方式绑定它:

<TextBox Text="{Binding Path=UserString, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource SpaceConverter}}" />

请注意,UserString必须位于当前DataContext

不要忘记在XAML中定义SpaceConverter。假设您正在使用UserControl,则执行此操作的一种方法是:

<UserControl.Resources>
   <local:SpaceConverter x:Key="SpaceConverter" />
</UserControl.Resources>

其中local被定义为包含SpaceConverter.cs的名称空间。

答案 1 :(得分:3)

我认为你的逻辑很好,但我会把它放在OnPreviewKeyDown的覆盖范围内。

答案 2 :(得分:1)

当控件失去焦点时,用_替换空格会不会更好?或者当用户将其键入时,是否绝对需要更换空间?