The Media Center Sandbox

Resources and discussion for developing experiences in the Windows Media Center platform.
Welcome to The Media Center Sandbox Sign in | Join | Help
in Search

Scroller behavior for panel containing focusable items

Last post 03-22-2010, 1:39 AM by AndyC. 5 replies.
Sort Posts: Previous Next
  •  03-08-2010, 1:08 PM 9593

    Scroller behavior for panel containing focusable items

    I am having a heck of a time with a scrolling issue in one of my application's pages. In it, I am trying to display a panel that should fill the entire screen. This panel represents status for a particular item and is bound to a repeater. Other items in the repeater should be off screen until the user clicks left or right on the keyboard/remote control (and ideally when the user clicks on on-screen carets with the mouse, but I'm saving that for later).

    Here's an example of what I'm looking for:

    Initial screen:

                         On-screen              Off-screen
                         --------------------
                         |                  |
                         | Item 1 Name      |   Item 2 Name          Item 3 Name
                         |                  |
                         | Item 1 Info      |   Item 2 Info          Item 3 Info
                         |                  |
                         | Command Button 1 |   Command Button 2     Command Button 3
                         |                  |
                         --------------------

    User Navigates to the right ->

    Off-screen           On-screen              Off-screen
                         --------------------
                         |                  |
      Item 1 Name        | Item 2 Name      |   Item 3 Name
                         |                  |
      Item 1 Info        | Item 2 Info      |   Item 3 Info
                         |                  |
      Command Button 1   | Command Button 2 |   Command Button 3
                         |                  |
                         --------------------

    The panel is center-locked so that scrolling to the next item causes the current item to scroll completely off screen. The next item slides in and is centered on-screen.

    This works great when my panel has no focusable items in it (like a command button), but once I put a button on the panel, the center-locked focus follows the selected button rather than staying with the panel.

    How can I avoid this? I feel like I've exhausted all of the ScrollingHandler and ScrollingData options, but I'm still not getting the behavior that I'd like. Some pseudo code is below:

    <Mcml xmlns="http://schemas.microsoft.com/2008/mcml"
          xmlns:me="Me">

    <UI Name="Test">

      <Content>
        <Panel Layout="Form" MouseInteractive="false">
          <Children>
            <Text Content="Screen Title">
              <LayoutInput>
                <FormLayoutInput Right="Parent,1,0" Top="Parent,0,0"/>
              </LayoutInput>
            </Text>
            <Panel Name="ContentPanel">
              <LayoutInput>
                <FormLayoutInput Left="Parent,0"
                                 Top="Parent,0.15"
                                 Right="Parent,1"
                                 Bottom="Parent,1"/>
              </LayoutInput>
              <Children>
                <me:ItemPanel Name="ItemPanel">
                  <LayoutInput>
                    <FormLayoutInput Left="Parent,0" Right="Parent,1"/>
                  </LayoutInput>
                </me:ItemPanel>
              </Children>
            </Panel>
          </Children>
        </Panel>
      </Content>

    </UI>

    <UI Name="ItemPanel">

      <Locals>
        <!-- Use Routed HandlerStage? -->
        <ScrollingHandler Name="ItemPanelScrollingHandler" HandlerStage="Bubbled"/>
        <ScrollingData Name="ItemPanelScrollingData" LockedPosition="0.5"/>
       
        <ArrayListDataSet Name="Items">
          <Source>
            <cor:String String="Item 1"/>
            <cor:String String="Item 2"/>
            <cor:String String="Item 3"/>
          </Source>
        </ArrayListDataSet>
      </Locals>

      <Rules>
        <Default Target="[ItemPanelScrollingHandler.ScrollingData]" Value="[ItemPanelScrollingData]"/>
        <Default Target="[ItemPanelScrollingData.Repeater]" Value="[ItemPanelRepeater]"/>
      </Rules>

      <Content>
        <Panel Name="ItemPanel" Navigation="ContainHorizontal">
          <Children>
            <Scroller Orientation="Horizontal"
                      ScrollingData="[ItemPanelScrollingData]">
              <Children>
                <Repeater Name="ItemPanelRepeater" Source="[Items]">
                  <Layout>
                    <!-- Big spacing gap here to ensure that repeated items stay off-screen -->
                    <FlowLayout Orientation="Horizontal"
                                Spacing="1000,1000"/>
                  </Layout>
                  <Content>
                    <me:RepeatItem Item="[RepeatedItem!cor:String]"
                                   Index="[RepeatedItemIndex]"/>
                  </Content>
                </Repeater>
              </Children>
            </Scroller>
          </Children>
        </Panel>
      </Content>

    </UI>

    <UI Name="RepeatItem">

      <Properties>
        <cor:String Name="Item" String="$Required"/>
        <Index Name="Index" Index="$Required"/>
      </Properties>

      <Locals>
        <Command Name="MyCommand"/>
      </Locals>

      <Rules>
        <Binding Target="[MyCommand.Description]" Source="[Device]"/>
      </Rules>

      <Content>
        <me:Button Name="RepeaterButton"
                   Item="[Item]"
                   Model="[MyCommand]"
                   Index="[Index]"/>
      </Content>

    </UI>

    <UI Name="RepeaterButton">

      <Properties>
        <ICommand Name="Model" ICommand="$Required"/>
        <cor:String Name="Item" String="$Required"/>
        <Index Name="Index" Index="$Required"/>
      </Properties>

      <Locals>
        <ClickHandler Name="Clicker"/>
        <Command Name="ItemCommand" Description="Do Something"/>
      </Locals>

      <Rules>
        <Binding Source="[Model.Description]" Target="[ItemNameLabel.Content]"/>
        <Binding Source="[Model]" Target="[Clicker.Command]"/>
      </Rules>

      <Content>
        <!-- Fills a large part of the panel area -->
        <Panel Name="RepeaterButtonPanel"
               Padding="5,5,5,5"
               MinimumSize="800,525"
               MaximumSize="800,525"
               Layout="Form">
          <Children>
            <Text Name="ItemNameLabel" Font="Calibri,36">
              <LayoutInput>
                <FormLayoutInput Top="Parent,0" Left="Parent,0,100"/>
              </LayoutInput>
            </Text>
            <Panel>
              <LayoutInput>
                <FormLayoutInput Top="ItemNameLabel,1,20" Left="ItemNameLabel,1,50"/>
              </LayoutInput>
              <Children>
                <Panel Name="ButtonPanel">
                  <Layout>
                    <FlowLayout Orientation="Vertical"/>
                  </Layout>
                  <Children>
                    <Panel>
                      <Layout>
                        <FlowLayout Orientation="Horizontal"/>
                      </Layout>
                      <Children>
                        <Text Content="Some Info: "/>
                        <Text Name="SomeInfoLabel"
                              Content="Some info goes here"/>
                        <!-- Commenting out the button below makes the scrolling work as desired, but I need the button! -->
                        <me:Button Name="ItemCommandButton"
                                  Model="[ItemCommand]"/>
                      </Children>
                    </Panel>
                  </Children>
                </Panel>
              </Children>
            </Panel>
          </Children>
        </Panel>
      </Content>

    </UI>

    <!-- This is from the default project, for testing purposes. -->
    <UI Name="Button">

      <Properties>
        <ICommand Name="Model"
                  ICommand="$Required"/>
        <Color Name="MyNonFocusColor"
               Color="Firebrick"/>
        <Color Name="MyFocusColor"
               Color="Yellow"/>
        <Color Name="MySelectedColor"
               Color="Green"/>
      </Properties>

      <Locals>
        <ClickHandler Name="Clicker"/>
      </Locals>

      <Rules>
        <Binding Source="[Model.Description]"
                 Target="[Label.Content]"/>
        <Binding Source="[Model]"
                 Target="[Clicker.Command]"/>
        <Condition Source="[Clicker.Clicking]"
                   SourceValue="true">
          <Actions>
            <Set Target="[Background.Content]"
                 Value="[MySelectedColor]"/>
          </Actions>
        </Condition>
        <Condition Source="[Input.KeyFocus]"
                   SourceValue="true">
          <Actions>
            <Set Target="[Background.Content]"
                 Value="[MyFocusColor]"/>
          </Actions>
        </Condition>
      </Rules>

      <Content>
        <ColorFill Name="Background"
                   Content="[MyNonFocusColor]"
                   Padding="5,5,5,5"
                   MinimumSize="200,50"
                   MaximumSize="200,50">
          <Children>
            <Text Name="Label"
                  Color="Black"
                  Font="Calibri,24"/>
          </Children>
        </ColorFill>
      </Content>

    </UI>

    </Mcml>

    I appreciate any and all help. I'm a bit new to MCML and am completely stymied with this one.
  •  03-08-2010, 11:16 PM 9594 in reply to 9593

    Re: Scroller behavior for panel containing focusable items

    Have a look at Input.CreateInterestOnFocus and Input.CreateInterestTarget- those might help. I think using these should cause the panel to retain the focus instead of the command button.

    Cheers,
    Andrew
  •  03-10-2010, 9:28 AM 9595 in reply to 9594

    Re: Scroller behavior for panel containing focusable items

    Thanks for your reply, AndyC. I'm at a loss as to how to use these commands. I understand how to assign them using "Default" in the rules section, but I'm not sure where to use them. To be clear, I want the command button(s) inside the panel to be focusable and clickable, but I don't want the scroller to follow their focus.

    There is a complete dearth of information on the 'net regarding these options. Just by mentioning them here, this thread is listed in the top three results for a Google search for "CreateInterestOnFocus" and top five for "CreateInterestTarget."

    I can almost get the functionality I desire using the BeginPadding and EndPadding options on ScrollingData, but when scrolling the next pane doesn't move to the center of the screen. I thought about dynamically changing the padding based on whether or not I'm "moving to" specific controls, but I have not yet been able to determine how to capture the scrolling event. Another ASCII art example:

    Initial screen (with focus padding boundaries marked by "!"):

                         On-screen              Off-screen
                         --------------------
                         |        !      !  |
                         | Item 1 Name   !  |   Item 2 Name          Item 3 Name
                         |        !      !  |
                         | Item 1 Info   !  |   Item 2 Info          Item 3 Info
                         |        !      !  |
                         |        !B1  B2!  |           B1  B2               B1  B2
                         |        !      !  |
                         --------------------


    Current behavior when user Navigates to the right (->) causes scroller to scroll far enough to show the B1, but not the whole panel.

    Off-screen           On-screen              Off-screen
                         --------------------
                         |        !      !  |
      Item 1 Name        |     Item 2 Name  |   Item 3 Name
                         |        !      !  |
      Item 1 Info        |     Item 2 Info  |   Item 3 Info
                         |        !      !  |
              B1  B2     |        !    B1! B|           B1  B2
                         |        !      !  |
                         --------------------

    If I could dynamically change the BeginPadding and EndPadding, I would get:

    User Navigates to the right ->

    Off-screen           On-screen              Off-screen
                         --------------------
                         |        !  !      |
      Item 1 Name        | Item 2 Name      |   Item 3 Name
                         |        !  !      |
      Item 1 Info        | Item 2 Info      |   Item 3 Info
                         |        !  !      |
              B1  B2     |        !B1! B2   |           B1  B2
                         |        !  !      |
                         --------------------

    Then immediately, I would change the BeginPadding back to "normal" (to the original focus boundaries) Navigating to the left would cause the same behavior, compressing the "focus column" to the location of the right-hand command button, then immediately changing it back to "normal" once that button is selected.

    This must be possible, no? I'm getting increasingly frustrated. I must be bringing in some baggage from other languages that is preventing me from seeing clearly.
  •  03-10-2010, 11:34 PM 9596 in reply to 9595

    Re: Scroller behavior for panel containing focusable items

    Have you seen any other add-in for Media Center which has a UI that behaves how you want it to? If so, then it is possible to do. If not, it's not neccessarily possible!

    What you've got to remember is that MCML was developed primarily to meet the needs of the Media Center application developers - it wasn't developed primarily as a platform for third party developers, so it may not do what you want, particularly if your UI design strays significantly from the Media Center UI design.

    When faced with this kind of situation, I usually look for a way to do things that is analagous to something that I know works in Media Center already.

    So in this instance, an alternative way of doing what you want is to not use a left/right scroller. Instead have a single static page as per the "on-screen" portion of your ascii art, and trap the left/right buttons; on left/right replace the content on screen with the appropriate left or right content depending on the button. Once you've got that working, then add ContentHide and ContentShow animations to give the illusion of animation (similar to the animation used when you change pivots in music library).

    Cheers,
    Andrew
  •  03-18-2010, 2:29 PM 9597 in reply to 9596

    Re: Scroller behavior for panel containing focusable items

    Thanks for taking the time to read my long posts and responding. After a fair bit of trial and error, I was able to approximate the behavior of the scrolling repeater using a single panel that is updated when the left/right arrows are clicked. I then use some animations to slide the panel off the screen to one side, then back onto the screen from the other side to simulate scrolling. It seems to work OK. More importantly, it doesn't go all wonky when the buttons in the panel receive focus.

    I've got a bit more work to do to make it work the way I need, but I am no longer pulling my hair out.

    I appreciate your prodding to look at things in a different way.

    Brad
  •  03-22-2010, 1:39 AM 9598 in reply to 9597

    Re: Scroller behavior for panel containing focusable items

    No problem - glad it's working out!

    Cheers,
    Andrew
View as RSS news feed in XML
Powered by Community Server, by Telligent Systems