4

I have this XAML code that works like a charm:

<TextBox Text="{Binding MyTextProperty, UpdateSourceTrigger=PropertyChanged}">
    <TextBox.InputBindings>
        <KeyBinding Command="{Binding MyOwnCommand}" CommandParameter="{Binding MyTextProperty}" Key="Enter" />
    </TextBox.InputBindings>
</TextBox>

There I have MyTextProperty that is passed as parameter to MyOwnCommand when I press enter key.

I do not want MyTextProperty updates every time I type a letter (because it has some logic asociated), but I do want it executes once I finish typing (without pressing enter key or losing the focus). The ideal solution would be this:

<TextBox Text="{Binding MyTextProperty, UpdateSourceTrigger=PropertyChanged, Delay=400}">
    <TextBox.InputBindings>
        <KeyBinding Command="{Binding MyOwnCommand}" CommandParameter="{Binding MyTextProperty}" Key="Enter" />
    </TextBox.InputBindings>
</TextBox>

The point here is the "Delay=400" parameter. It waits until I finish typing and then updates MyTextProperty.

But the problem I found at this point is that if I type something and immediately press enter, MyOwnCommand is called but MyTextProperty is not updated yet (it will be updated 400ms later).

I have tried to add the same delay in CommandParameter="{Binding MyTextProperty, Delay=400}", but it does not work.

What is the right approach to pass the CommandParameter once MyTextProperty has been updated?

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Carlos
  • 1,638
  • 5
  • 21
  • 39
  • It might be ugly but you can remove that `KeyBinding` and move your command call into `Setter` of the `MyTextProperty` this way you won't have synchronization problems. – Eldar Jan 05 '22 at 11:32
  • @Eldar but... how can I know from the setter in the ViewModel if the enter key has been pressed or not? – Carlos Jan 05 '22 at 11:56
  • Why do you need to know if enter is pressed? – Eldar Jan 05 '22 at 12:01
  • @Eldar `MyOwnCommand` must only be executed when enter key is pressed, but there is a different logic in the setter that must be executed every time we change `MyTextProperty` – Carlos Jan 05 '22 at 12:31
  • Just an idea but could you not just put that logic into a converter and use it in conjunction with your code? Also if your command is only dealing with that one Text property, you don't need to pass it as you already have access to it in your VM. – XAMlMAX Jan 05 '22 at 13:19
  • @XAMlMAX both the setter of `MyTextProperty` and `MyOwnCommand` are in a separate project, in a generic class (). I do not think it is possible what you propose. Better than doing it, I prefer to remove the "Delay=400" parameter ;) I know some ways to avoid this problem (e.g. removing the Delay parameter), but I ask because I would like to know how to deal with this problem in a smart way. Thank you – Carlos Jan 05 '22 at 13:43
  • @XAMlMAX although I do not pass `MyTextProperty` as a parameter, because I already have access to it in the VM, it is not updated when we launch the command, so I think the problem would be the same. – Carlos Jan 05 '22 at 13:46
  • 1
    @Carlos, try binding CommandParameter to TextBox.Text directly – ASh Jan 05 '22 at 18:46

2 Answers2

4

TextBox.Text changes immediately after user types symbol from keyboard, even if there is a delay to send value to bound property. So you can bind CommandParameter to TextBox.Text directly:

<TextBox Name="MyTextBox" 
         Text="{Binding MyTextProperty, UpdateSourceTrigger=PropertyChanged, Delay=400}">
    <TextBox.InputBindings>
        <KeyBinding Command="{Binding MyOwnCommand}" 
                    CommandParameter="{Binding Text, ElementName=MyTextBox}" 
                    Key="Enter" />
    </TextBox.InputBindings>
</TextBox>
ASh
  • 34,632
  • 9
  • 60
  • 82
0

but I do want it executes once I finish typing

I would split out this property into different properties. Then only have the enter Command extract the final value, set in the final property and excecute the final step.


// bound to the active textbox, which receives character by character changes
public string MyTextProperty { get { ... } 
                               set { ...do individual key press logic here... }

public string MyTextProperty_Final  { }

public void EnterCommand()
{
  MyTextProperty_Final = MyTextProperty;
  FinalOperationCommand(MyTextProperty_Final); // Or FinalOperationCommand.Invoke(MyTextProperty_Final);
}

public void FinalOperationCommand(string text)
{
   ... delay if needed ...
   ... Do stuff with MyTextProperty_Final
}

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122