Search code examples
c#wpfkey-bindingsivalueconverter

wpf Change the text of Textbox on KeyBinding Gesture


how can i solve this using MVVM pattern, and I am using Devexpress MVVM. I have many textbox in form.

And i need to set the textbox text into "[blank]" when the user press the Ctrl+B and the current text of the textbox is null or ""

But i am looking for a way to use the IValueConverter if possible

I have a class similar to this

public class BlankText : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (string.IsNullOrEmpty(value.ToString()))
                return "[blank]";
            else
                return value;
        }
    }

And i have this code in the resources

    <UserControl.Resources>
        <c:BlankText x:Key="BlankText"/>
    </UserControl.Resources>

This is my TextBox

           <TextBox Text="{Binding District}"  >
                <TextBox.InputBindings>
                    <KeyBinding Gesture="Ctrl+B">
                    </KeyBinding>
                </TextBox.InputBindings>
            </TextBox>

But my problem is how can i call it on keypress? Am i doing it right?


Solution

  • In order to perform actions using KeyBinding, you can't use IValueConverter. IValueConverters are for converting values, not performing actions. What you need is to define a class that implements ICommand, and then assign an instance of that class to KeyBinding.Command.

    public class BlankCommand : ICommand 
    {
        public MyViewModel ViewModel { get; }
    
        public BlankCommand(MyViewModel vm)
        {
            this.ViewModel = vm;
        }
    
        public void Execute(object parameter) 
        {
            // parameter is the name of the property to modify
    
            var type = ViewModel.GetType();
            var prop = type.GetProperty(parameter as string);
            var value = prop.GetValue(ViewModel);
    
            if(string.IsNullOrEmpty(value))
                prop.SetValue(ViewModel, "[blank]");
        }
    
        public boolean CanExecute(object parameter) => true;
    
        public event EventHandler CanExecuteChanged;
    }
    

    Then create an instance of this class and attach it to your ViewModel so that the KeyBinding can access it:

    <TextBox Text="{Binding District}">
        <TextBox.InputBindings>
            <KeyBinding Gesture="Ctrl+B" Command="{Binding MyBlankCommand}" CommandParameter="District"/>
        </TextBox.InputBindings>
    </TextBox>
    

    Changing the text to say "[blank]" when the user presses a keyboard shortcut is a weird UX pattern, however. I would suggest adding a placeholder to the text box instead.