DelegateCommand with enum as parameter

Oct 20, 2008 at 7:06 AM
Has anyone had any luck creating a delegate command where the parameter is an enum? I get an exception when I try to do this and was hoping someone had already coming up with a solution to this?

Cheers

Justin
Oct 20, 2008 at 8:55 PM

Hi,

 

Here’s an example of how to implement it. This example has a module (MyModule) containing a view (MyView) with an interface (IMyView) and a presenter (MyViewPresenter). These are the steps:

1- Create the enumeration in MyModule, for example:

namespace Example.MyModule

{

    public enum MyEnum

    {

        One,

        Two,

        Three

    }

}

 

2- Define a method in the interface of the view to set an instance of the command in the view, as follows:

public interface IMyView

{

    void SetEnumerationCommand(ICommand enumerationCommand);

}

 

3- Define a property of type DelegateCommand<MyEnum> in the code behind of the view, and implement the SetEnumerationCommand method of IMyView, so that the presenter can set the property with a new instance of the command:

public partial class MyView : UserControl, IMyView

{

    public DelegateCommand<MyEnum> EnumerationCommand { get; private set; }

 

    #region IMyView Members

 

    public void SetEnumerationCommand(ICommand enumerationCommand)

    {

        this.EnumerationCommand = enumerationCommand as DelegateCommand<MyEnum>;

        this.DataContext = EnumerationCommand;

    }

 

    #endregion

}

 

4- Define, in the Presenter of the view, the CanExecute and Execute methods, and create a new instance of the command with these two methods:

public class MyViewPresenter

{

    public MyViewPresenter(MyView view)

    {

        View = view;

        View.SetEnumerationCommand(new DelegateCommand<MyEnum>(GetNumber, CanGetNumber));

    }

 

    public IMyView View { get; private set; }

 

    private bool CanGetNumber(MyEnum arg)

    {

        //provide here the necessary code to make the command enabled or disabled.

    }

 

    private void GetNumber(MyEnum num)

    {

        //your code goes here.

    }

}

 

5- Finally, in the XAML of the view, you should add the namespace of MyModule in order to use MyEnum in the CommandParameter property. I.e.:

<UserControl x:Class="Example.MyModule.MyView"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:myModule="clr-namespace:Example.MyModule"

    Height="300" Width="300">

    <Grid>

        <Button Content="Click for two" Command="{Binding}" CommandParameter="{x:Static myModule:MyEnum.Two}" />

    </Grid>

</UserControl>

 

If you want to send the parameter via code and not through XAML, you must call the Execute method of the command, as follows:

EnumerationCommand.Execute(MyEnum.Two);

 

Please, let me know if this helps.

 

Ignacio Baumann Fonay

http://blogs.southworks.net/ibaumann/

Oct 21, 2008 at 12:23 AM
<style> </style> <link id="RADEDITORSTYLESHEET0" rel="stylesheet" type="text/css" href="/WebResource.axd?d=fnoTs0l3l_ZndIzAraVVQrrG1nwB_npClj6qlQs68DG_3_1fo1b02gpIoo4_J3Ww8MwggLk07wFThXdb5sSU1yNjF1potX6_HMMalzQHiRM1&t=633577871800000000"> <link id="RADEDITORSTYLESHEET1" rel="stylesheet" type="text/css" href="http://i1.codeplex.com/css/StyleSheet.ashx?css=RadEditorBody&v=13635">Here's a more specific example of what my issues was

        public enum TestEnum
        {
            Value1,
            Value2
        }

Then, in the Constructor for a Window I wanted to do.

DelegateCommand<TestEnum> delegateCommand= new DelegateCommand<TestEnum>(ExecuteMethod, CanExecute );
Button b = new Button;
b.Command = delegateCommand;
b.CommandParameter = TestEnum.Value1;

Methods are as follows

        public void ExecuteMethod(TestEnum selectedValue)
        {
            //do some work
        }

        public bool CanExecute(TestEnum selectedValue)
        {
            return true;
        }

Trying to do this fails every time.

The reason, as I discovered, is that you need to set the CommandParameter FIRST, so we change it to

Button b = new Button;
b.CommandParameter = TestEnum.Value1;
b.Command = delegateCommand;

this is because CanExecute will get called when the command is assigned to the button in code. Since there is no parameter assigned, CanExecute will be passed a null value, triggering an exception. This seems like a generally poor design descision to me, but now I know about it I can work around it.

Thanks for taking the time to post the example code Ignacio.

Regards

Justin
Oct 5, 2011 at 7:24 PM

Hi,

I found this discussion while hit an error when I try to create DelegateCommand<MyEnum>(OnExecute). The error says "T for DelegateCommand<T> is not an object nor Nullable. (System.InvalidCastException). I'm using Prism4 and is DelegateCommand still working with Enum type as parameter?

Thanks!

Oct 5, 2011 at 11:48 PM

Hi Julie,

Last time I checked this still worked fine. Can you paste an example of the XAML you are using that is creating the error? It sounds like you're running in to the problem I was having where your initial value is not set and so casting to an enum fails (enums obviously can't be null).

Cheers

JT

Oct 6, 2011 at 3:10 AM

It dosn't seem like the problem in Xaml. It didn't like this line (ProcessStepCategory is the enum)

SetDemProcessStepsCommand = new DelegateCommand<ProcessStepCategory>(OnSetExecuted);
Does the default need to be set at this point?
Thanks!
Developer
Oct 6, 2011 at 2:45 PM

Hi,

Unlike in Prism v2, the implementation of the DelegateCommand in Prism v4 checks that the associated parameter is a nullable type. This was probably made to avoid this issue.

One possible approach to use an enum type as the parameter type for your command would be to wrap your enum type in the Nullable<T> struct. This way, the command should work correctly.

You will find more information about this in the following blog post from Brian Noyes:

I hope you find this helpful.

Agustin Adami
http://blogs.southworks.net/aadami

Oct 13, 2011 at 12:22 AM

Julie,

Did you end up getting this sorted out or is it still giving you grief?

Cheers

JT

Oct 13, 2011 at 3:53 PM

Yes.

I defined the command this way and it worked:

SetProcessCommand = new DelegateCommand<Nullable<ProcessType

>>(OnSetProcessCommand);

Thanks.