Update binding when ENTER triggers default button action

Dec 19, 2011 at 1:19 PM

In a Catel DataWindow the OK button is the default button.

If (for example) a TextBox is edited and the the ENTER key is pressed the action is taken (and the ViewModel Save is called) without the TextBox losing focus, so the binding is not updated and the ViewModel never sees the new text value.

Changing the TextBox  UpdateSourceTrigger to PropertyChanged is not an acceptable solution. I think the DataWindow base class should include some code to update the bindings before taking the default action. Or is there a better way?

(I realise that this problem is in WPF and is not Catel's fault, but I think Catel should include a generic solution.)

Coordinator
Dec 19, 2011 at 1:20 PM

We are aware of this issue in Silverlight, and fixed it in the latest beta. However, we have never encountered this issue in WPF. We will first focus the OK button before invoking it.

Dec 19, 2011 at 1:22 PM

Good solution! Thanks for the rapid response.

Do you have any idea when the fix will release?

Do you have any suggestions about how to handle the problem until then?


Coordinator
Dec 19, 2011 at 1:37 PM

For now, you can handle the SaveViewModel event in the view and focus something else. Then it should update the binding before the view model is actually saved. I think I can produce a beta tonight, a real fix will be available in 2.5 (will be released within 2 weeks).

Dec 19, 2011 at 1:48 PM
Edited Dec 19, 2011 at 2:21 PM

Ah! Good idea! A small problem is that I would have to create something else to focus - my data window has only a TextBox at present.

I have fixed it this way (it seems to work but it's not yet fully tested). You may like to bake something like this into Catel. It handles the binding update without having to change focus, which would be an issue if the default button did not end up closing the view.

  • Add to the catel:DataWindow statement in the XAML of the view: 
    BindingGroup="{Binding FixEnterBindingGroup}"
  • Add the following code to the view model:
    private System.Windows.Data.BindingGroup fixEnterBindingGroup;
    
    public System.Windows.Data.BindingGroup FixEnterBindingGroup
      {
      get
        {
        if (fixEnterBindingGroup == null)
          {
          fixEnterBindingGroup = new System.Windows.Data.BindingGroup();
          fixEnterBindingGroup.Name = "FixEnterBindingGroup";
          }
        return fixEnterBindingGroup;
        }
      }
    
  • Add the following code at the beginning of the Save override in the ViewModel:
    FixEnterBindingGroup.CommitEdit();

----------------- EDIT -----------------

On further testing I see that my fix doesn't work. I think the BindingGroup is being created too soon; it probably needs to be created in response to the View's Loaded event. I'll keep working on it ...

----------------- EDIT 2 ---------------

Ok, I was wrong. The BindingGroup needs to be created earlier. I now create and set the BindingGroup as the first thing in the View constructor. The binding in the XAML is no longer necessary. I'll post again with a corrected solution.

Dec 19, 2011 at 2:33 PM

Here's the working version of my fix:

  • Add the following code at the beginning of the View constructor (before InitializeComponent):
    BindingGroup = ((SomeViewModel)DataContext).FixEnterBindingGroup = new System.Windows.Data.BindingGroup();
    
  • Add the following code to the view model:
    internal System.Windows.Data.BindingGroup FixEnterBindingGroup { get; set; }
  • Add the following code at the beginning of the Save override in the ViewModel:
    FixEnterBindingGroup.CommitEdit();

    I think it would be quite good if this was part of the DataWindow base class (or wherever else is more appropriate).

  • Coordinator
    Dec 19, 2011 at 2:35 PM

    Great, thanks for the fix! I will take a look at this tonight and fix it in Catel itself.

    Dec 19, 2011 at 2:40 PM

    I see this as a potential fix for the same problem that would occur if any other keyboard accelerators were used to invoke commands (not just ENTER for the default button). I guess a CommitEdit function (or something similar) would need to be accessible in the ViewModel so that the user could call it whenever necessary.

    After all this I would like to say (as I should have said at the start) THANKS for a great framework. I am only just getting to grips with using Catel but I think it will make my life a lot easier! (That's a Good Thing, whatever my wife may think :) )

    Coordinator
    Dec 19, 2011 at 6:29 PM

    You are very welcome, we really hope you like it. If you ever have any questions, ideas or bug reports, don't hesitate to contact us! As you can see, we are quite responsive :)

    I have fixed the issue, but not in the way you did it. I used the same solution as for Silverlight (to keep the solutions as close to eachother as possible without interfering with other "hacks"). Thus, we are handling the KeyUp event ourselves and focus the default (accept) button when there are no modifiers and the key is enter.

    You can download the latest beta here:

    http://dl.dropbox.com/u/8455721/Catel%20beta.zip