简体   繁体   中英

KeyBinding to a function in code behind? WPF/MVVM

I have a TextBox, when user presses Enter on their keyboard the value in textbox gets "confirmed" and the string is formatted to the correct amount of decimals.

So if the textbox should have 1 decimal and the user writes "30" without any decimals and presses Enter, then the textbox is automatically updated to "30.0".

The problem is that the CaretIndex is placed at positon 0 when this happens. If i press enter with the Caret after 0 like "30|" then it gets reset to "|30.0" instead of "30.0|" how i want it.

I have a command that gets fired when enter is pressed inside the textbox. However, the command is inside the View Model, and i should not be touching View things (the caret) inside View Model. So how should i go on about doing it?

I was thinking of instead of binding to a command in view model i bind to a function in view (code behind) and from that function i raise the command in VM and set caret, like so:

    private void EnterPressed()
    {
        ((ParamTextNodeVM)DataContext).EnterCmd.Execute(null);
        ValueBox.CaretIndex = ValueBox.Text.Length;
    }

However, this does not work:

   <TextBox>
       <TextBox.InputBindings>
           <KeyBinding Key="Enter" Command="{Binding EnterPressed}"/>
       </TextBox.InputBindings>
    </TextBox>

How do i bind "Command" to "EnterPressed" that is inside code behind?

Binding to a function in the code behind would work, but would violate the MVVM pattern. A relay command allows you to bind a command in the view to the view model.

 /// <summary>
/// A basic command that runs an Action
/// </summary>
public class RelayCommand : ICommand
{
    #region Private Members

    /// <summary>
    /// The action to run
    /// </summary>
    private Action mAction;

    #endregion

    #region Public Events

    /// <summary>
    /// The event thats fired when the <see cref="CanExecute(object)"/> value has changed
    /// </summary>
    public event EventHandler CanExecuteChanged = (sender, e) => { };

    #endregion

    #region Constructor

    /// <summary>
    /// Default constructor
    /// </summary>
    public RelayCommand(Action action)
    {
        mAction = action;
    }

    #endregion

    #region Command Methods

    /// <summary>
    /// A relay command can always execute
    /// </summary>
    /// <param name="parameter"></param>
    /// <returns></returns>
    public bool CanExecute(object parameter)
    {
        return true;
    }

    /// <summary>
    /// Executes the commands Action
    /// </summary>
    /// <param name="parameter"></param>
    public void Execute(object parameter)
    {
        mAction();
    }

    #endregion
}

Within the view model itself, you will need to declare the command as a parameter

public ICommand EnterPressedCommand { get; set; }

Finally, within the constructor of the ViewModel, you will need to assign the command to a function

EnterPressedCommand = new RelayCommand(() => EnterPressed());

This should allow the command to be triggered from the view, and execute your EnterPressed method

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM