sgonchar
Topic Author
Posts: 48
Joined: 15 Mar 2021, 22:11

controller B nav sometimes triggers multiple times, sometimes not at all

05 Apr 2021, 21:52

Hello,

Our controller B nav sometimes triggers multiple times, sometimes not at all .. depending on order of frames in main window.

Our mainwindow.xaml has the frames like so, note "page" is is what is currently visible, each page has a Back button.
      <Frame x:Name="ScreenC" Width="1920" Height="1080" Source="Views/ScreenC.xaml" Focusable="False" />
      <Frame x:Name="ScreenB" Width="1920" Height="1080" Source="Views/ScreenB.xaml" Focusable="False" />
      <Frame x:Name="ScreenA" Width="1920" Height="1080" Source="Views/ScreenA.xaml" Focusable="False" />
      <i:Interaction.Triggers>
        <ei:DataTrigger Binding="{Binding page}" Value="{StaticResource VIEW_SCREENA}">
          <ei:ChangePropertyAction PropertyName="Visibility" TargetName="ScreenA" Value="Visible" />
        </ei:DataTrigger>
        <ei:DataTrigger Binding="{Binding page}" Comparison="NotEqual" Value="{StaticResource VIEW_SCREENA}">
          <ei:ChangePropertyAction PropertyName="Visibility" TargetName="ScreenA" Value="Hidden" /> 
        </ei:DataTrigger>
        <!-- more triggers for B/C -->
Buttons in each screen are defined as so (note empty command param is does default back).
    <Button Name="ButtonBack" Style="{StaticResource MenuButtonStyle}" Command="{Binding Navigate}" CommandParameter="" Focusable="False" >
      <i:Interaction.Triggers>
        <noesis:GamepadTrigger FiredOn="ButtonDown" Button="Cancel">
          <i:InvokeCommandAction Command="{Binding Navigate}"  CommandParameter=""/>
          <i:Interaction.Behaviors>
            <ei:ConditionBehavior>
              <ei:ConditionalExpression>
                <ei:ComparisonCondition LeftOperand="{Binding Path=IsVisible, ElementName=ButtonBack}" Operator="Equal" RightOperand="True"/>
              </ei:ConditionalExpression>
            </ei:ConditionBehavior>
          </i:Interaction.Behaviors>
        </noesis:GamepadTrigger>
      </i:Interaction.Triggers>
      <Button.Content>
      <!-- button contents -->

Expectation: Flow is ScreenA > ScreenB > ScreenC

Problem 1: Pressing "B" on Screen C, will take you all the way back to screen A. Binding "Navigate" will trigger twice. However, inspector confirms that at any one point only one "ButtonBack" property "IsVisible" is set to true.

We think that act of pressing "B" changes the "page" and input sometimes gets forwarded to next page even though it should have been consumed in the last button press.

Caviat: if we order mainwindow.xaml to be like so, the problem of double back goes away. Binding "Navigate" is triggered only once.
      <Frame x:Name="ScreenA" Width="1920" Height="1080" Source="Views/ScreenA.xaml" Focusable="False" />
      <Frame x:Name="ScreenB" Width="1920" Height="1080" Source="Views/ScreenB.xaml" Focusable="False" />
      <Frame x:Name="ScreenC" Width="1920" Height="1080" Source="Views/ScreenC.xaml" Focusable="False" />
It's a bit of a short term solution for us as we expect some flows to be non linear.

Question 1: why does order of things in mainwindow.xaml matter?

Question 2: Is it the case of non-consumed back input? How does one force consume input in a button? Or something else you think might be happening?



Problem 2: EDIT: Problem 2 solved, see next post On a branching screen flow sometimes "B" just doesn't get triggered, Binding "Navigate" will not trigger.
It is not the matter of <ei:ConditionBehavior>, problem persists with or without.
This worked literally 4 days ago before more screens were added (ala my previous post about triggering buttons from cpp. )
However, I'm still trying to boil down the problem to a simple example.
I only have a suspicion it's to do with some kind of focus issue, something else is capturing the input. The Inspector says the current focus is still on an element of last screen that is currently not visible, so it might be consuming input but not acting on it? My dud screen that doesn't go back does have SetFocusAction, which worked elsewhere, though we disabled focus entirely on that page as nothing can be in focus. This page did not change in days .. so problem is created elsewhere, possibly on earlier page that forces focus on input text.
         <i:Interaction.Triggers>
          <i:EventTrigger EventName="Loaded"> <!-- MouseEnter, or Targetname doesn't this work -->
            <noesis:SetFocusAction />
          </i:EventTrigger>
        </i:Interaction.Triggers>
Last edited by sgonchar on 05 Apr 2021, 22:46, edited 4 times in total.
 
sgonchar
Topic Author
Posts: 48
Joined: 15 Mar 2021, 22:11

Re: controller B nav sometimes triggers multiple times, sometimes not at all

05 Apr 2021, 22:13

Re Problem 2 solved.
I was missing "Focusable="True" on user control of entire screen, so setfocusAction probably didn't trigger. There's nothing on the screen to focus, so it might not really need to be focusable, but it does make the input flow correctly (maybe _something_ on frame needs to be focused for the entire frame to get any input?)
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: controller B nav sometimes triggers multiple times, sometimes not at all

06 Apr 2021, 19:54

GamepadTrigger, when property ActiveOnFocus is not set to true, registers on the root element of the tree. So if you have 3 triggers (one for each screen), the 3 of them will be registered on the root of the tree and all will be triggered when the gamepad button is pressed if the ConditionBehavior is fullfilled.
why does order of things in mainwindow.xaml matter?
The trigger order depends on how they are defined in the tree, because they register on the event as they are attached. This means that if you have screens defined as C|B|A, when trigger on C navigates back to B it makes B screen visible, then B trigger is evaluated and as it is visible it also navigates back to A.
maybe _something_ on frame needs to be focused for the entire frame to get any input?
Key and Gamepad events are routed events that originate in the focused element (see this post). If there is no focused element in the frame, no element of the frame could receive the event.

Just a suggestion, if the trigger of the back button on each screen always binds to the same Navigate command, won't be better to just have a single GamepadTrigger on the MainWindow?
 
sgonchar
Topic Author
Posts: 48
Joined: 15 Mar 2021, 22:11

Re: controller B nav sometimes triggers multiple times, sometimes not at all

06 Apr 2021, 21:23

Ok, thank you very much for the explanation, that makes sense now.

Is there a way to consume a button click event so that when visual tree changes it won't pick up the same button event again? Maybe something a delay before changing visual tree would work (seems hacky)?
Just a suggestion, if the trigger of the back button on each screen always binds to the same Navigate command, won't be better to just have a single GamepadTrigger on the MainWindow?
We kinda do something similar, we have a component with a set of buttons that is shared across many screens, it makes sure correct buttons and hints are visible when needed. I'm not sure a common component on main window can work as it has to be z-interlaced with other elements in the screen (between the background and foreground elements).
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: controller B nav sometimes triggers multiple times, sometimes not at all

07 Apr 2021, 16:49

Is there a way to consume a button click event so that when visual tree changes it won't pick up the same button event again? Maybe something a delay before changing visual tree would work (seems hacky)?
The default implementation of the GamepadTrigger doesn't handle the event, but the source code is available so you can extend it or create a new trigger that handles the event to prevent other triggers to invoke their actions.
void GamepadTrigger::OnButtonPress(BaseComponent*, const Noesis::KeyEventArgs& e)
{
    if (GetButton() == (GamepadButton)(e.originalKey - Noesis::Key_GamepadLeft))
    {
        InvokeActions(0);
        
        // You can add code here to handle the event
        e.handled = true;
    }
}
We kinda do something similar, we have a component with a set of buttons that is shared across many screens, it makes sure correct buttons and hints are visible when needed. I'm not sure a common component on main window can work as it has to be z-interlaced with other elements in the screen (between the background and foreground elements).
I was referring to define a single GamepadTrigger in the root of the MainWindow for the Back action, there is no need to move the buttons there only the trigger. Back buttons can stay in their screens or wherever you need them to be defined. The trigger is independant from the back button because you are not setting ActiveOnFocus to true, so the event registration is done in the root element of the tree not in the element where the trigger is attached.
 
sgonchar
Topic Author
Posts: 48
Joined: 15 Mar 2021, 22:11

Re: controller B nav sometimes triggers multiple times, sometimes not at all

07 Apr 2021, 17:11

Ok, great. Thank you, we will look into extending OnButtonPress.

Also thank you for explaining the main window back solution, it's a neat way to handle it, I'm hoping there wouldn't be desync between visual state and button being able to trigger, I'll try this shortly.

Who is online

Users browsing this forum: Google [Bot] and 73 guests