Как изменить текст в TextCompositionEventArgs - PullRequest
6 голосов
/ 28 февраля 2012

C # WPF - у меня есть настраиваемая редактируемая сетка данных, которая использует мои собственные настраиваемые столбцы, которые наследуются от DataGridTextColumn. В своем классе столбцов я переопределяю GenerateEditingElement, чтобы я мог автоматически устанавливать такие вещи, как MaxLength, CharacterCasing и т. Д.

Проблема в том, что когда пользователь выделяет ячейку, а затем вводит свой первый символ, сетка данных автоматически входит в режим редактирования. Так что мой GenerateEditingElement срабатывает, и я могу настроить текстовое поле. К сожалению, это слишком поздно для набора символов, и в TextCompositionEventArgs уже есть строчный символ. Последующие типы символов имеют правильный регистр.

Класс столбца PrepareCellForEdit - это то, что запускается следующим, и у него есть TextCompositionEventArgs. Тем не менее, я не могу изменить текст. Я получаю ошибки компиляции, что сеттер НЕ доступен. (хотя в справке по intellisense для свойства указано «получить и установить»).

Могу ли я каким-то образом программно перенести регистр символов в текстовое поле? ИЛИ ЖЕ Как я могу изменить этот текст в TextCompositionEventArgs?

1 Ответ

0 голосов
/ 05 марта 2012

Основная идея - подписаться на событие TextChanged TextBox. Но хитрость в том, что вы не можете обновить свойства Text непосредственно в этом обработчике событий. Вы должны использовать небольшую задержку, чтобы сделать это. Вот пример, который работает хорошо:

    public struct MyData
    {
        public string Name { set; get; }
    }

    public MainWindow()
    {
        InitializeComponent();
        ObservableCollection<MyData> oc = new ObservableCollection<MyData> { new MyData(), new MyData() };
        grid.ItemsSource = oc;
    }

    private void Grid_OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        var col = new DataGridTextColumn();
        Style myStyle = new Style(typeof(TextBox));
        // subsribe to TextChanged event
        myStyle.Setters.Add(new EventSetter(TextBoxBase.TextChangedEvent, new TextChangedEventHandler(OnTextChanged)));
        col.EditingElementStyle = myStyle;
        var binding = new Binding("Name") {Mode = BindingMode.TwoWay};
        col.Binding = binding;
        e.Column = col;
    }

    private static void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += Worker_DoWork;
        worker.RunWorkerAsync(textBox);
        worker.RunWorkerCompleted += Worker_RunWorkerCompleted;          
    }

    static void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        TextBox textBox = e.Result as TextBox;
        if (textBox != null)
        {
            textBox.Text = textBox.Text.ToUpper();
            textBox.CaretIndex = textBox.Text.Length;
        }
    }

    static void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        Thread.Sleep(1);// This is the trick :)
        e.Result = e.Argument;
    }
...