Search code examples
c#wpfmvvmdata-bindingicommand

How to trigger KeyUp Event in MVVM using ICommand


I have created this simple view:

enter image description here

Now when I press the RETURN key while the cursor being inside one of these 2 textboxes, I want the "Suchen" = SEARCH button to trigger (KeyUp Event).

I know how to easily do this in the code behind but I want to do it in MVVM (in my view model class) with an ICommand. In the code behind I used the (autogenerated) KeyEventArgs parameter.

I tried it in MVVM using ICommand but the Command method gives me an error claiming that I would need to instantiate an object for the KeyEventArgs argument. In the code behind (non-mvvm-like) I did not need to instantiate anything because the KeyEventArgs parameter was "autogenerated" just like the method. So I didn't have to worry about that.

How do I make the KeyUp event work in my MVVM project? For this question to answer I provide you the following shortened code:

XAML-View:

 <StackPanel Height="423" VerticalAlignment="Bottom">
        <Label Name="lblArtikelbezeichnung" Content="Artikelbezeichnung:" Margin="20, 20, 20, 0"></Label>
        <TextBox Name="txtArtikelbezeichnung" 
                 Width="Auto" 
                 Margin="20, 0, 20, 0"
                 IsEnabled="{Binding BezEnabled}"
                 Text="{Binding BezText}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="TextChanged">
                    <i:InvokeCommandAction Command="{Binding TextChangedBez}" />
                </i:EventTrigger>
                <i:EventTrigger EventName="KeyUp">
                    <i:InvokeCommandAction Command="{Binding KeyUpBez}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBox>
        <!--TextChanged="txtArtikelbezeichnung_TextChanged" 
                 KeyUp="txtArtikelbezeichnung_KeyUp"-->
        <Label Name="lblLieferant" Content="Lieferant:" Margin="20, 0, 20, 0"></Label>
        <TextBox Name="txtLieferant" 
                 Width="Auto" 
                 Margin="20, 0, 20, 0"
                 IsEnabled="{Binding LiefEnabled}"
                 Text="{Binding LiefText}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="TextChanged">
                    <i:InvokeCommandAction Command="{Binding TextChangedLief}" />
                </i:EventTrigger>
                <i:EventTrigger EventName="KeyUp">
                    <i:InvokeCommandAction Command="{Binding KeyUpLief}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBox>
            <!--TextChanged="txtLieferant_TextChanged" 
                 KeyUp="txtLieferant_KeyUp"-->
        <Button Name="btnSuchen" 
                Content="Suchen" 
                Width="100" Height="25" 
                Margin="20, 10,240, 10" 
                Command="{Binding GefilterteSuche}">
        </Button>
...
<StackPanel>

Code Behind:

    using System.Windows;

    namespace Lieferscheine
    {
        /// <summary>
        /// Interaktionslogik für artikelHinzu.xaml
        /// </summary>
    public partial class artikelHinzu : Window
    {

        public artikelHinzu()
        {
            InitializeComponent();
            DataContext = new ArtikelHinzuViewModel();
        }     
    }
}

View Model:

    public class ArtikelHinzuViewModel : INotifyPropertyChanged
    {              
//ICommands (shortened)
        public ICommand GefilterteSuche => new DelegateCommand<object>(SucheArtikel);                     
        public ICommand KeyUpLief => new DelegateCommand<KeyEventArgs>(KeyUpLieferant);       
        public ICommand KeyUpBez => new DelegateCommand<KeyEventArgs>(KeyUpBezeichnung);

 //INotifyPropertyChanged      
        public event PropertyChangedEventHandler PropertyChanged;
        public virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        //Konstruktor
        public ArtikelHinzuViewModel()
        {

        }

//ICommand methods (shortened for reasons of simplicity)        

         //KeyUp Events (THIS PART IS MY PROBLEM)      
        private void KeyUpBezeichnung(KeyEventArgs e) //the argument is obligatory but it does not have an instantiated object which is why an error fires...
        {
//since I need to create an object for KeyEventArgs I tried this but it is useless...
        /*e = new KeyEventArgs(Keyboard.PrimaryDevice,
        Keyboard.PrimaryDevice.ActiveSource,
        0, Key.Back);
//I need to access this e.Key property but don't know how in my case! That is the actual problem...
            if (e.Key == Key.Return)
            {
                object o = new object();
                SucheArtikel(o);
            }
            */
        }
//same problem here as above...
        private void KeyUpLieferant(KeyEventArgs e)
        {
            /*
        e = new KeyEventArgs(Keyboard.PrimaryDevice,
        Keyboard.PrimaryDevice.ActiveSource,
        0, Key.Back);

            if (e.Key == Key.Return)
            {
                object o = new object();
                SucheArtikel(o);
            }
             */
        }

    }

Solution

  • Using InputBindings is easier:

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