Command with parameters

Topics: Questions
Aug 20, 2012 at 10:45 PM

Hi everyone,

I am trying to bind an event of a textbox (textchange event) to a command.

The command takes a TextChangedEventArgs parameter but I got an error when creating the command.

Here is my command code

       /// <summary>
        /// Gets the name command.
        /// </summary>
        public Command ChangeNumberOfFiles { get; private set; }

        /// <summary>
        /// Method to invoke when the name command is executed.
        /// </summary>
        private void OnChangeNumberOfFilesExecute(TextChangedEventArgs e)
        {
            var textBox = (TextBox) e.Source;

            FileNumber = Convert.ToInt32(textBox.Text);


        }

Here is my viewmodel constructor:

/// <summary>
        /// Initializes a new instance of the <see cref="HomeWindowViewModel"/> class.
        /// </summary>
        public HomeWindowViewModel()
        {
            FolderToWatch = Settings.Default.FolderToWatch;
            FileNumber = Settings.Default.NumberOfEmails;
            Messages = new ObservableCollection<MessageModel>(Utils.FilesRetrieve.RetrieveEmail(FolderToWatch, FileNumber));
            ChangeNumberOfFiles = new Command(OnChangeNumberOfFilesExecute);
        }

The error I got is:

"Expected a method with 'void OnChangeNumberOfFilesExecute()' signature".

 

Is there any way to specify the parameters when creating a new command?

 

Thank you


regis

Aug 20, 2012 at 11:06 PM
Edited Aug 20, 2012 at 11:09 PM

Hello again,

 

I have been searching for this problem for some time and of course after publishing this post I have been able to got the project to compile.

 

Here is what I changed:

 

 /// <summary>
        /// Gets the name command.
        /// </summary>
        public Command<TextChangedEventArgs> ChangeNumberOfFiles { get; private set; }

/// <summary>
        /// Initializes a new instance of the <see cref="HomeWindowViewModel"/> class.
        /// </summary>
        public HomeWindowViewModel()
        {
            FolderToWatch = Settings.Default.FolderToWatch;
            FileNumber = Settings.Default.NumberOfEmails;
            Messages = new ObservableCollection<MessageModel>(Utils.FilesRetrieve.RetrieveEmail(FolderToWatch, FileNumber));
            ChangeNumberOfFiles = new Command<TextChangedEventArgs>(OnChangeNumberOfFilesExecute);
        }

But now the trigger doesn't fire at all. Here is my XAML:

 

<TextBox Text="{Binding FileNumber, UpdateSourceTrigger=PropertyChanged}" />
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="TextChanged">
                        <catel:EventToCommand Command="{Binding ChangeNumberOfFiles}" 
                                              DisableAssociatedObjectOnCannotExecute="False" PassEventArgsToCommand="True"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>

Am I missing something?

 

Thank you

regis

Coordinator
Aug 21, 2012 at 10:08 AM

Interesting, should work. Did you try calling LogManager.RegisterDebugListener to see what the output window has to say?

Aug 21, 2012 at 11:19 PM

hi GeertvanHorrik

I tried calling LogManager.RegisterDebugListener (didn't know about this one, very useful for tracing the different states, Catel is really an amazing framework).

Sadly it has nothing special to say.

I tried changing the event from "TextChanged" to "LostFocus", modifying the signature command to accept an object parameter and the event is firing correctly.

I kept the object parameter in the signature and change the trigger event name back to "TextChanged" and it's not working. Seems top be realated to the textbox itself. Not sure what is really going on.

That is really strange.

Would you have any idea why?

 

Thank you

 

Regis

Aug 22, 2012 at 11:08 PM

Hello,

 

I carry on finding a way to solve my problem and end up on this article:

http://joyfulwpf.blogspot.ca/2009/05/mvvm-invoking-command-on-attached-event.html

 

Unless I am wrong "textChanged"is a routed event. That would explain why it won't work out of the box.

I decided to call my function in the setter of the property bound to the textbox. Not as elegeant but it's working.

 

Thank you for your time

 

Regis

Coordinator
Aug 23, 2012 at 11:08 AM

I thought we implemented support for routed events in 3.2 for the EventToCommand. Will take a look at it.

Sorry for my late replies btw, codeplex seems to have trouble sending email notifications...

Aug 23, 2012 at 6:12 PM

Haven't routed events always been supported?  Almost all WPF events are routed events so it seems like EventToCommand would have limited use if it didn't.  I know I have been using it for routed events like Button.Click and PreviewMouseMove since Catel 2.something.  

BTW, LostFocus is also a routed event, and castaingregis says above that his code works if he changes the event to LostFocus.  

Coordinator
Aug 24, 2012 at 11:18 AM

Yes, it was another behavior that we implemented support for. Strange that it is not working.

@castaingregis: can you provide a small repro?

Sep 25, 2012 at 10:47 PM

Hi GeertvanHorrik,

 

Sorry I didn't get back earlier. I finally found what the problem was when I try to provide a small project that would reproduce the problem.

If you check the code I posted earlier you can notice that the trigger is not attached to the textbox (the textbox tag is closed before the trigger).

 

This is what I wrote:

<TextBox Text="{Binding FileNumber, UpdateSourceTrigger=PropertyChanged}" />
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="TextChanged">
                        <catel:EventToCommand Command="{Binding ChangeNumberOfFiles}" 
                                              DisableAssociatedObjectOnCannotExecute="False" PassEventArgsToCommand="True"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>

 

this is what it should really be

 

<TextBox Text="{Binding FileNumber, UpdateSourceTrigger=PropertyChanged}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="TextChanged">
                        <catel:EventToCommand Command="{Binding ChangeNumberOfFiles}" 
                                              DisableAssociatedObjectOnCannotExecute="False" PassEventArgsToCommand="True"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers></Textbox>

I am really sorry for having missed such a dumb error.

And Thank again for your support

 

Regis

Coordinator
Sep 26, 2012 at 7:13 AM

No problem, thanks for letting us know!