tags:

views:

3795

answers:

3

Hi! I want to create editable combo box with the following properties: 1. Bind the text property to my data model. 2. The data model may override the changes in the GUI, even in Selection changed. E.g. I can choose from 1, 2, 3 I choose 2, but some component down under changes it to 3. 3. Update the data model on the following events: 1. Selection Changed 2. Lose focus 3. Enter pressed (should behave the same as lost focus).

I've been able to create such control, but it's pretty ugly (using many hacks) and I hoped there's a simpler way…

Thanks in advance

A: 

Ok, I here's what I've done, and its not that ugly:

 /// <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();
        }
    }

}
A: 

The simplest way to do this is to use the UpdateSourceTrigger property on the binding. You may not be able to match your current behavior exactly, but you may find that it is comparable.

The UpdateSourceTrigger property controls when the target of the binding updates the source. Different WPF controls have different default values for this property when bound.

Here are your options:

UpdateSourceTrigger.Default = Allow target control to determine UpdateSourceTrigger mode.

UpdateSourceTrigger.Explicit = Only update source when someone calls BindingExpression.UpdateSource();

UpdateSourceTrigger.LostFocus = Automatically update binding source whenever the target looses focus. This way a change can be completed, and then the binding is updated after the user moves on.

UpdateSourceTrigger.PropertyChanged = Whenever the DependencyProperty on the target changes values the source is updated immediatly. Most UserControls do not default to this property because it requires more binding updates (can be a performance issue).

Josh G
A: 

Josh I have a situation where ComboBox IsEditable property is set and the value entered should update the ItemsSource to a Collection I am binding for ComboBox. I am using MVVM model. Any Help? I have used Selectedvalue property to make first item selected

Vaishnavi