0

I am mapping an xbox controller and want a way for the user to change what key does what in the program. I use a dictionary with the key as a ControllerEventArgs ( custom event args) and value is Action, which is the function that will be invoked when the button is pressed.

Everything is in place except one part: We are able to open a combo box with all they buttons (A Pressed, A Released, B, X, Y, etc) and using reflection and attributes I display all the possible methods (actions) the button can make. So the user goes ahead and chooses it - But now I have the method name in the MethodInfo[] and I need it as an Action to pass to/modify my dictionary. Any way to do this? I am new to reflection and attributes.

Dictionary is defined as:

public Dictionary<ControllerEventArgs, Action<object>> ButtonMapping = 
    new Dictionary<ControllerEventArgs, Action<object>>(new ControllerComparison());

This is my event for when a button is pushed:

private void basicevent(object source, ControllerEventArgs e)
{
    if (!AltState)
    {
        if (ButtonMapping.ContainsKey(e))
        {
            ButtonMapping[e].Invoke(e);
        }
        else //debug
        {
            MessageBox.Show("Key not found in dictionary.\nButton Name: " + e.Name + "\nAction: " + e.Action + "\nAlt Mode: FALSE");
        }
    }
    else
    {
        if (AltButtonMapping.ContainsKey(e))
        {
            AltButtonMapping[e].Invoke(e);
        }
        else //debug
        {
            MessageBox.Show("Key not found in dictionary.\nButton Name: " + e.Name + "\nAction: " + e.Action + "\nAlt Mode: TRUE");
        }
    } 
}

And this is where I am trying to modify the value of the dictionary ( You can see my commented out stuff I was trying near the bottom)

private void SaveKeyMapping_Click(object sender, RoutedEventArgs e)
{
    ComboBoxItem item = (ComboBoxItem)KeySelection.SelectedItem;
    string SelectedItem = item.Content.ToString();
    string SelectedAction = AvailableActions.SelectedItem.ToString();
    AvailableActions.Items.Clear();
    CurrentAction.Items.Clear();
    if ((SelectedItem == "RightThumb Moved") || (SelectedItem == "LeftThumb Moved"))
    {
        //Joystick specific
    }
    else if ((SelectedItem == "RightTrigger Pressed") || (SelectedItem == "RightTrigger Released") || (SelectedItem == "LeftTrigger Pressed") || (SelectedItem == "LeftTrigger Released"))
    {
        //Trigger specific
    }
    else
    {
        //Button specific
        string[] SelectedButton = SelectedItem.Split(SelectedItem[1]);
        ControllerEventArgs args = new ControllerEventArgs { Name = SelectedButton[0], Action = SelectedButton[1] };

        //Convert MethodInfo to Action<object>....

        // Action<object> action = (Action<object>)Delegate.CreateDelegate(typeof(Action<object>), ButtonMethods[1]);
        //Action<object> ac = delegate(object instance) { ButtonMethods[0].Invoke(instance, null); };
        // Action ac = (Action)Delegate.CreateDelegate(typeof(Action), ButtonMethods[1]);
        Action<object> newaction = controller.LightControl;
        //change value in dictionary

        controller.ButtonMapping[args] = newaction;
    }
}
AGB
  • 2,230
  • 1
  • 14
  • 21
Fivestar
  • 323
  • 1
  • 5
  • 18
  • 1
    Can you show the code that you have? Does these methods have parameters? – Yacoub Massad May 31 '16 at 20:48
  • Are the methods static? If not, the question, [Invoke method by MethodInfo](http://stackoverflow.com/q/919826/945456) is relevant. The answer to [Calling a static method using a Type](http://stackoverflow.com/a/3384992/945456) may also help. – Jeff B May 31 '16 at 21:03
  • @YacoubMassad I added a bit of code. The methods that are invoked have parameters of object args. – Fivestar May 31 '16 at 21:12
  • @JeffBridgman Okay Ill take a look – Fivestar May 31 '16 at 21:12
  • So, why Action newaction = (instance) => methodInfo.Invoke(instance, null); does not work? Or you have multiple MethodInfos and want to invoke them all? – Evk May 31 '16 at 21:15
  • @Evk Umm Im not really sure. A lot of things I tried ended in it throwing exceptions during run time. I gave up on it and decided to change my dictionary to accept a string as the value, and in my event I handle whatever action needs to be called based on that string instead of having the action directly in the value field. – Fivestar May 31 '16 at 22:09
  • This assumes you already have a valid method info (from your code above). In this case the MethodInfo would be for a function which takes no parameters, Try: `Action newAction = new Action ( () => { ButtonMethods[0].Invoke(instance, null); }); controller.ButtonMapping[args] = newAction;` – Clay Ver Valen May 31 '16 at 22:49
  • There are many other related questions, in addition to the marked duplicate, involving variations on the question of creating delegate instances from reflection-derived objects. See https://stackoverflow.com/search?q=%5Bc%23%5D+create+delegate+from+methodinfo for some more examples. If none of these address your concern, please post a new question, making sure to include a good [mcve] that shows clearly what you're trying to do and what _specific_ problem you are having accomplishing that. – Peter Duniho Jun 01 '16 at 01:16

0 Answers0