2

I am having some trouble with an editable ComboBox and the updating of a binding. Currently I have a ComboBox where its UpdateSourceTrigger=LostFocus this is because I need to wait for the user to finish inputting somthing before I decide if the value is a new value (and thus create a new one).

Unfortunately, I have another feature which requires the binding to update when the value has changed aswell. Aka, LostFocus is no good to me in this case. As selecting a new value within the ComboBox it doesn't cause the LostFocus to fire (obviously). So I need to find a way to force update the binding.

I have looked into the SelectionChanged and forcing the update on the binding:

    <i:EventTrigger EventName="SelectionChanged">
        <i:InvokeCommandAction Command="{Binding ParentConversation.ViewModel.ComboSelectionChanged}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:StoryForgeComboBox}}}"/>
    </i:EventTrigger>

And updating the binding in code behind like so:

be = BindingOperations.GetBindingExpression(ele, ComboBox.TextProperty);
if (be != null)
{
    be.UpdateSource();
}

Unfortunately I CANNOT update the binding at this point as the value has yet to change. See this stackoverflow topic: ComboBox- SelectionChanged event has old value, not new value

There is a trick where you can possibly use the DropDownClosed event and then update the binding, this works but does not work if you use the Up/Down arrow keys which never opens the ComboBox. Also hooking into KeyUp and KeyDown is too early. The binding cant be updated yet.

So my question is, when is a good time to say "Hey Mr Combo Box, You can update your bindings now".

Cheers.

Community
  • 1
  • 1
Asheh
  • 1,547
  • 16
  • 25
  • `So I need to find a way to force update the binding` - what exactly you want to achieve? In MVVM ViewModel implements [`INotifyPropertyChanged`](http://msdn.microsoft.com/en-us/library/ms743695.aspx), so that updating from source occurs implicitly if you change property value (or explicitly if you rise event) and in other direction, to source, it is (as you say) `UpdateSourceTrigger=ValueChanged`. Which one is your problem? – Sinatr Dec 03 '14 at 16:19

1 Answers1

3

You can change the SelectionChanged event trigger to LostFocus:

    <ComboBox
        IsEditable="True"
        ItemsSource="{Binding Items}"
        SelectedItem="{Binding SelectedItem}"
        Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}">
        <i:Interaction.Triggers>
            <i:EventTrigger
                EventName="LostFocus">
                <i:InvokeCommandAction
                    Command="{Binding Command}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </ComboBox>
  • When the user types, Text is updated.
  • When the user types and the ComboBox finds a match in the Items, SelectedItem is changed.
  • When the user types, the ComboBox does not find a match and a item was previously selected, SelectedItem is set to null.
  • When the user selects an item, both SelectedItem and Text are updated.
  • When the user leaves the ComboBox (losing focus), Command is triggered.
  • When the user has typed text and opens the drop down list, Command is triggered.
  • EDIT: strangely enough Command is also triggered when it receives focus.

Is this the behavior you want?

Sjeijoet
  • 741
  • 4
  • 20
  • I never considered trying to bind both the Text and the Selected item. This may just work!! – Asheh Dec 03 '14 at 16:28
  • 1
    Thank you very much. Occams Razor. Always. – Asheh Dec 03 '14 at 16:32
  • 2
    As hantoun says, you have to be careful with the LostFocus event with the ComboBox in edit mode. When the ComboBox initially receives focus, it gives focus to the textbox within, causing the ComboBox to raise a LostFocus event. You can hack around this by adding a LostFocus trigger directly to the ComboBox's textbox `var textbox = (TextBox)comboBox.Template.FindName("PART_EditableTextBox", combobox); textbox.LostFocus += (sender, args) => viewModel.Command.Execute();` – ptsoccer Dec 04 '14 at 14:33