UpdateSourceTrigger = PropertyChanged and Converter - PullRequest
3 голосов
/ 12 июня 2009

У меня есть простой Converter, который добавляет символ "+" к положительному числу, которое вводится в TextBox. Когда номер введен, я хочу инициировать какое-либо действие, но я не хочу ждать, пока TextBox потеряет фокус: я хочу обновить привязку немедленно, когда пользователь вводит текст.

Поведение по умолчанию TextBox заключается в том, что когда пользователь уходит от поля, источник привязки обновляется (UpdateSourceTrigger = LostFocus). В этом сценарии мой конвертер работает как положено, и добавляется +. Однако, когда я изменяю его на следующее, + + никогда не добавляется .

<TextBox Text="{Binding Value, Converter={StaticResource PlusConverter}, UpdateSourceTrigger=PropertyChanged}" />

Я могу себе представить, что есть веская причина, по которой мой метод converter.Convert () не вызывается. Я хотел бы иметь следующее поведение:

  1. Когда пользователь вводит текст, источник немедленно обновляется
  2. Когда TextBox теряет фокус, добавляется +.

Теперь я ищу хороший, но особенно общий способ сделать это (так как у меня в приложении много таких текстовых блоков). До сих пор я не смог найти правильное решение.

Ответы [ 4 ]

1 голос
/ 13 июня 2009

Еще одна вещь, которую вы можете сделать, это отредактировать шаблон для TextBox и немного переместить фактический PART_ContentHost вправо, а затем TextBlock указать +/- часть; т.е. изменить шаблон TextBox с:

Control
- Border
-- PART_ContentHost (the actual editing part)

в

Control
- Border
-- Horizontal StackPanel
--- TextBlock (contains +/- sign, has 2px right margin)
--- PART_ContentHost (actual editable section)

Затем привяжите содержимое TextBlock к тексту, но с помощью конвертера, который пишет «+» или «-». Таким образом, пользователь не может удалить часть +/-, и вам не нужно беспокоиться о ее разборе; это также облегчает задачу, если вы хотите сделать что-то вроде красного знака негатива или чего-то подобного.

1 голос
/ 15 июня 2009

Спасибо за ваши ответы! Я сам немного углубился в эту проблему и нашел следующее решение (которым я не совсем доволен, но оно отлично работает)

Я создал CustomControl, который добавляет функциональность в TextBox.

Предоставлен обработчик события для события LostFocus Когда происходит это событие, мой конвертер называется.

Однако способ разрешения конвертера не очень удовлетворителен (я беру его из стиля, связанного с моим TextBox). Стиль имеет Setter для свойства Text. Из этого установщика я могу получить доступ к своему конвертеру.

Конечно, я мог бы также создать «PlusTextBox», но я использую разные конвертеры и мне нужно универсальное решение.

public class TextBoxEx : TextBox
{
    public TextBoxEx()
    {
        AddHandler(LostFocusEvent,
          new RoutedEventHandler(CallConverter), true);
    }

    public Type SourceType
    {
        get { return (Type)GetValue(SourceTypeProperty); }
        set { SetValue(SourceTypeProperty, value); }
    }

    // Using a DependencyProperty as the backing store for SourceType.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SourceTypeProperty =
        DependencyProperty.Register("SourceType", typeof(Type), typeof(TextBoxEx), new UIPropertyMetadata(null));

    private static void CallConverter(object sender, RoutedEventArgs e)
    {
        TextBoxEx textBoxEx = sender as TextBoxEx;
        if (textBoxEx.Style == null) {
            return;
        }
        if (textBoxEx.SourceType == null) {
        }
        foreach (Setter setter in textBoxEx.Style.Setters) {
            if (setter.Property.ToString() == "Text") {
                if (! (setter.Value is Binding) ) {
                    return;
                }
                Binding binding = setter.Value as Binding;
                if (binding.Converter == null) {
                    return;
                }
                object value = binding.Converter.ConvertBack(textBoxEx.Text, textBoxEx.SourceType, binding.ConverterParameter, System.Globalization.CultureInfo.CurrentCulture);
                value = binding.Converter.Convert(value, typeof(string), binding.ConverterParameter, System.Globalization.CultureInfo.CurrentCulture);
                if (!(value is string)) {
                    return;
                }
                textBoxEx.Text = (string)value;
            }
        }
    }
}
1 голос
/ 12 июня 2009

Согласен с Кентом B, вам необходимо опубликовать код конвертера.

Мне удалось заставить часть 1 работать с простым конвертером (я связываю второй не преобразованный TextBlock, чтобы показать, что значение действительно обновляется).

Однако, если я понимаю вашу часть 2, вы пытаетесь получить текст TextBox , чтобы он обновлялся символом «+» после потери фокуса. Это немного сложнее, и я не думаю, что вы сможете сделать это только с помощью IConverter. Если это можно сделать, я бы тоже хотел узнать ответ.

То, что вы, по сути, просите, - это поведение ввода с водяными знаками, например позволяют пользователю вводить некоторые данные и правильно их форматировать (как в базовом DataBinding, так и в пользовательском интерфейсе). Самое быстрое / самое грязное решение для этого - обработать LostFocus в TextBoxes, но, поскольку вы используете его во всем приложении, это может быть неосуществимо.

Вы также можете обернуть TextBox в свой собственный UserControl. Если вы посмотрите на реализацию DatePicker, реализованную в WPFToolkit, то он имеет похожее поведение: позволяет пользователю вводить текст произвольной формы, затем автоматически преобразует значение в DateTime (если оно допустимо) и отображает DateTime в локализованном формате.

НТН.

0 голосов
/ 02 июля 2009

Не могли бы вы просто проверить текущий фокус клавиатуры в вашем конвертере? Что-то вроде:

TextBox focusedTextBox = Keyboard.FocusedElement as TextBox;
if (focusedTextBox == null || focusedTextBox != senderOrWhatever)
{
 ' this is where you'd add the +, because the textbox doesn't have focus.
}
...