InvokeCommandAction not invoking command
Hi, I was having issues with InvokeCommandAction in my Unity project, and I believe I've set it up correctly.
I have created a DelegateCommand extension class, exactly as described here. No changes, except for the namespace to match the other extensions I have.
https://github.com/Noesis/Tutorials/blo ... Command.cs
In my code-behind, the relevant section looks like this:
I have validated this command with a Button! And when clicking on it, the button fires the command as expected. Here's the button, and its CommandBinding.
The issue is only happening when I try to bind it to an "InvokeCommandAction" inside of a gamepad trigger. I know the trigger works because, I created a fade-in storyboard which plays when it's triggered. Also, it isn't only broken in the gamepad trigger, I also tried a "Loaded" event trigger and it failed to call there as well.
A few extra details: The name "PageRoot" is my custom UserControl, and the delegate is in the code-behind for this control. This control itself is not the Data Context! And that's why I have the ElementName specified so I bind to the correct one. I did also try moving the DelegateCommand property into the ViewModel that I have set as the DataContext, but unfortunately it didn't work there either. In both situations it seems to bind without any errors or warnings. And I can set some breakpoints in the DelegateCommand. I see it set up correctly in its constructor, but Execute is never called.
Finally, with the noesis GUI.Inspector tool, I was able to see that the InvokeCommandAction was successfully bound to the Accept property. I have no errors or warnings. I have an image of that here but I did anonymize the data context since it has my project name and would have taken some time to refactor. I promise, the function exists in that context 😊
So to summarize the things I've tried and tests I've done:
Is there another rule about getting this to work that I've missed when setting this up?
Also, it's not related to the issue but, I could take this opportunity to mention a few things I noticed in the docs as I was browsing:
In both of these links below, in their respective xaml demo, the <b:Interaction.Triggers> tag is not closed. Also in the GamepadTrigger Class description for the "ActiveOnFocus" property it describes the behaviour with "KeyDown" and "KeyUp" terminology instead of "ButtonDown" and "ButtonUp".
https://www.noesisengine.com/docs/App.I ... igger.html
https://www.noesisengine.com/docs/App.I ... igger.html
I have created a DelegateCommand extension class, exactly as described here. No changes, except for the namespace to match the other extensions I have.
https://github.com/Noesis/Tutorials/blo ... Command.cs
In my code-behind, the relevant section looks like this:
Code: Select all
public DelegateCommand Accept { get; private set; }
private void Accept_Pressed(object parameter)
{
UnityEngine.Debug.Log($"Accept was pressed!");
}
public MyCustomPage()
{
InitializeComponent();
Accept = new DelegateCommand(Accept_Pressed);
}
Code: Select all
<Button Content="Test Command"
Command="{Binding Accept, ElementName=PageRoot}"
FontSize="30" />
Code: Select all
<UserControl.Resources>
<ResourceDictionary>
<Storyboard x:Key="Intro">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="Root">
<EasingDoubleKeyFrame KeyTime="0"
Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.3"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ResourceDictionary>
</UserControl.Resources>
<b:Interaction.Triggers>
<noesis:GamepadTrigger FiredOn="ButtonUp"
Button="Accept">
<b:ControlStoryboardAction Storyboard="{StaticResource Intro}" />
<b:InvokeCommandAction Command="{Binding Accept, ElementName=PageRoot}" /> <!-- Fails to execute! -->
</noesis:GamepadTrigger>
<b:Interaction.Triggers>
Finally, with the noesis GUI.Inspector tool, I was able to see that the InvokeCommandAction was successfully bound to the Accept property. I have no errors or warnings. I have an image of that here but I did anonymize the data context since it has my project name and would have taken some time to refactor. I promise, the function exists in that context 😊
So to summarize the things I've tried and tests I've done:
- The button test seems to suggest the DelegateCommand is fine.
- The animation test shows the trigger works.
- The Inspector shows that it's bound with the correct path, and there are no errors or warnings about failed bindings.
Is there another rule about getting this to work that I've missed when setting this up?
Also, it's not related to the issue but, I could take this opportunity to mention a few things I noticed in the docs as I was browsing:
In both of these links below, in their respective xaml demo, the <b:Interaction.Triggers> tag is not closed. Also in the GamepadTrigger Class description for the "ActiveOnFocus" property it describes the behaviour with "KeyDown" and "KeyUp" terminology instead of "ButtonDown" and "ButtonUp".
https://www.noesisengine.com/docs/App.I ... igger.html
https://www.noesisengine.com/docs/App.I ... igger.html
Re: InvokeCommandAction not invoking command
I've run into this issue again, this time with an event trigger for selection changed inside of a ListBox.
I really believe this has to be user-error on my end.. 😂 But no clue what it could be..
Another detail maybe that's important: The 'b' alias I have is for this schema. Which again, seems to not be an issue when using the triggers themselves, only the InvokeCommandAction seems to be not working for me. And again, it does bind (at least, there are no errors saying it failed to bind)..
Code: Select all
<b:Interaction.Triggers>
<b:EventTrigger EventName="SelectionChanged">
<b:InvokeCommandAction Command="{Binding ListBoxSelectionChanged, ElementName=PageRoot}" /> <!-- Also fails to execute! -->
</b:EventTrigger>
</b:Interaction.Triggers>
Another detail maybe that's important: The 'b' alias I have is for this schema. Which again, seems to not be an issue when using the triggers themselves, only the InvokeCommandAction seems to be not working for me. And again, it does bind (at least, there are no errors saying it failed to bind)..
Code: Select all
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
Re: InvokeCommandAction not invoking command
I guess we can close this soon! As expected it was user error,
Essentially, since the DelegateCommand class from the documentation uses a constructor to set up its action, and so I was most likely overwriting the referenced class by creating a new object after setting the DataContext for my NoesisView. This is why nothing "failed" to bind, since I believe it was bound successfully but this was just bound to the default object and it was overwritten.
Anyway, this is my bad. I realize now I could have also just called OnPropertyChanged for the delegate command after setting it as an alternative to just creating it before setting the DataContext to my ViewModel. I didn't realize it had "changed" necessarily since I thought I'd set it up at the right point in time. But no, I set it up after setting the data context.
Cheers!
Essentially, since the DelegateCommand class from the documentation uses a constructor to set up its action, and so I was most likely overwriting the referenced class by creating a new object after setting the DataContext for my NoesisView. This is why nothing "failed" to bind, since I believe it was bound successfully but this was just bound to the default object and it was overwritten.
Anyway, this is my bad. I realize now I could have also just called OnPropertyChanged for the delegate command after setting it as an alternative to just creating it before setting the DataContext to my ViewModel. I didn't realize it had "changed" necessarily since I thought I'd set it up at the right point in time. But no, I set it up after setting the data context.
Cheers!
-
sfernandez
Site Admin
- Posts: 3014
- Joined:
Re: InvokeCommandAction not invoking command
Thanks for this feedback, we will fix the documentation for the next release.Also, it's not related to the issue but, I could take this opportunity to mention a few things I noticed in the docs as I was browsing:
In both of these links below, in their respective xaml demo, the <b:Interaction.Triggers> tag is not closed. Also in the GamepadTrigger Class description for the "ActiveOnFocus" property it describes the behaviour with "KeyDown" and "KeyUp" terminology instead of "ButtonDown" and "ButtonUp".
That could explain what happened.this was just bound to the default object and it was overwritten
Yes, your data context class can implement the INotifyPropertyChanged interface to notify any changes in the properties, and the UI will listen to that event and update accordingly.I realize now I could have also just called OnPropertyChanged for the delegate command after setting it as an alternative to just creating it before setting the DataContext to my ViewModel.
I think we can mark this as fixed then.