Tuesday, April 15, 2008

I'm building a small sample for EFContrib, and thought it would be cool to use the new MVC framework 'Prism' for it. Prism is a new framework currently under development by the patterns and practices group. It is not feature complete and everything might change in the next drop. But, well, it's fun to see such a framework develop and how best to understand it, than by building something simple with it!

I'm trying to do something fairly basic: I have a view that has a button on it. If the button is pressed, a form should popup where we can search for employees. When the search is over, the result should be accessible by my controller.
At the same time though, I know that I'm going to have a detail screen as well with the same button on it. Here the button chooses a teamleader for the employee.

I want to define the command once, but need my controllers to behave differently. It's quite possible that I would be better off just creating two commands (one for the detail screen and one for the employee screen). You could argue that they perform different actions: choose an employee versus choose a teamleader.
But I don't swing that way and I feel it should be possible to have the same command on a lot of buttons and let the appropriate controller deal with it.

In the prism project are a few base classes for commands: the DelegateCommand and also the ActiveAwareDispatchCommand. As far as I can see, they allow a command to be hooked up by multiple views and allow controller to register their interest in them.
I created a static class with my 'ChooseEmployee' command:

 

    public static class EmployeeChooserCommands
    {
        public static ActiveAwareMultiDispatchCommand ChooseEmployee = new ActiveAwareMultiDispatchCommand();
      }

Now, my views couple their buttons to this command in the regular way.

In my definition of MVC a controller is responsible for the logic and thus handles this command.

        protected ActiveAwareDelegateCommand chooseEmployeeCommand;

It defines it's own command and in the ctor hooks it up:

            chooseEmployeeCommand = new ActiveAwareDelegateCommand(Choose, CanChoose);
            // register this instance on the global
            EmployeeChooserCommands.ChooseEmployee.RegisterCommand(chooseEmployeeCommand);

The last line will make this controller react to executions of the command by every source.

This is the pattern that I see in the current Prism reference implementation project.

The fun thing about the ActiveAwareDelegate is the way you can set it as Active and not-Active. If it is not active, it will not be queried for canExecute information and its execute delegate will not be called.

So, what I did, was to let my views implement the IActiveAware interface and throw an event when they lose or get focus. The corresponding controllers react to it in this way:

        void view_IsActiveChanged(object sender, EventArgs e)
        {
            chooseEmployeeCommand.IsActive = view.IsActive;
          }

Setting the command to only be active when the view is active.
Downside here is that if one view is active, it gets to decide on the canExecute result, but all buttons in all views will react to it: clearly not what we want.

So, I feel I'm on the wrong track here. I really miss being able to set some sort of 'affinity' to the RegisterCommand method. I would like to let that method know I'm interested in commands where the source is equal to my view. But then again, maybe I should just create different commands :-)

Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):