Каков наилучший способ создания текстового поля WPF, заменяющего пробелы подчеркиванием? - PullRequest
3 голосов
/ 06 октября 2010

Я создаю FilteredTextBox в WPF, который подклассов включает включенный 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 ]

4 голосов
/ 06 октября 2010

Я бы связал 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.

Не забудьте также определить SpaceConverter в XAML. Один из способов сделать это, предполагая, что вы работаете с UserControl, будет:

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

Где local определяется как пространство имен, содержащее SpaceConverter.cs.

3 голосов
/ 06 октября 2010

Я думаю, что ваша логика хороша, но я бы поставил ее в переопределение OnPreviewKeyDown.

1 голос
/ 06 октября 2010

Было бы лучше просто заменить пробел на _, когда элемент управления теряет фокус, или вам абсолютно необходимо заменить его, когда пользователь вводит его?

...