Редактируемый ComboBox - PullRequest
6 голосов
/ 24 февраля 2009

Я хочу создать редактируемое поле со списком со следующими свойствами:

  1. Свяжите свойство text с моей моделью данных.
  2. Модель данных может переопределять изменения в графическом интерфейсе, даже если выбор был изменен. Например. Я могу выбрать из 1, 2, 3, я выбираю 2, но какой-то компонент под ним меняет его на 3.
  3. Обновите модель данных для следующих событий:

    1. Выбор изменен
    2. Потерять фокус
    3. Ввод нажат (должен вести себя так же, как потерянный фокус).

Мне удалось создать такой элемент управления, но он довольно уродлив (с использованием множества хаков), и я надеялся, что есть более простой способ ...

Заранее спасибо

Ответы [ 2 ]

2 голосов
/ 08 марта 2009

Хорошо, вот что я сделал, и это не так страшно:

 /// <summary>
/// Editable combo box which updates the data model on the following:
/// 1. Select## Heading ##ion changed
/// 2. Lost focus
/// 3. Enter or Return pressed
/// 
/// In order for this to work, the EditableComboBox requires the follows, when binding:
/// The data model value should be bounded to the Text property of the ComboBox
/// The binding expression UpdateSourceTrigger property should be set to LostFocus
/// e.g. in XAML:
/// <PmsEditableComboBox Text="{Binding Path=MyValue, UpdateSourceTrigger=LostFocus}"
/// ItemsSource="{Binding Path=MyMenu}"/>
/// </summary>
public class PmsEditableComboBox : ComboBox
{
    /// <summary>
    /// Initializes a new instance of the <see cref="PmsEditableComboBox"/> class.
    /// </summary>
    public PmsEditableComboBox()
        : base()
    {
        // When TextSearch enabled we'll get some unwanted behaviour when typing
        // (i.e. the content is taken from the DropDown instead from the text)
        IsTextSearchEnabled = false;
        IsEditable = true;
    }

    /// <summary>
    /// Use KeyUp and not KeyDown because when the DropDown is opened and Enter is pressed
    /// We'll get only KeyUp event
    /// </summary>
    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);

        // Update binding source on Enter
        if (e.Key == Key.Return || e.Key == Key.Enter)
        {
            UpdateDataSource();
        }
    }

    /// <summary>
    /// The Text property binding will be updated when selection changes
    /// </summary>
    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        base.OnSelectionChanged(e);
        UpdateDataSource();
    }

    /// <summary>
    /// Updates the data source.
    /// </summary>
    private void UpdateDataSource()
    {
        BindingExpression expression = GetBindingExpression(ComboBox.TextProperty);
        if (expression != null)
        {
            expression.UpdateSource();
        }
    }

}
0 голосов
/ 11 марта 2009

Самый простой способ сделать это - использовать свойство UpdateSourceTrigger в привязке. Возможно, вы не сможете точно соответствовать своему текущему поведению, но вы можете обнаружить, что оно сопоставимо.

Свойство UpdateSourceTrigger определяет, когда цель привязки обновляет источник. Различные элементы управления WPF имеют разные значения по умолчанию для этого свойства при привязке.

Вот ваши варианты:

UpdateSourceTrigger.Default = Разрешить целевому элементу управления определять режим UpdateSourceTrigger.

UpdateSourceTrigger.Explicit = Обновлять источник, только когда кто-то вызывает BindingExpression.UpdateSource ();

UpdateSourceTrigger.LostFocus = Автоматически обновлять источник привязки всякий раз, когда цель теряет фокус. Таким образом, изменение может быть завершено, а затем привязка обновляется после того, как пользователь переходит.

UpdateSourceTrigger.PropertyChanged = Всякий раз, когда свойство DependencyProperty в целевом объекте изменяет значения, источник обновляется немедленно. Большинство UserControls не используют это свойство по умолчанию, поскольку оно требует большего количества обязательных обновлений (может быть проблема с производительностью).

...