locked
How to access controls within HubSections?

    Question

  • Hi,

    I am working on a Win8.1 app and the main page uses a Hub. Within each HubSection there are different control that I need to access from Code. The content of a HubSection is not defined directly but by a DataTemplate. Because of this the content cannot be accessed by a x:Name. The following is not possible:

    <Page ...>
       <Grid>
          ...
          <Hub ...>
             <HubSection x:Name="ListSection">
                <DataTemplate>
                    <local:MyListUserControl x:Name="ListControl"/>
                </DataTemplate>
             </HubSection>
    
             <HubSection x:Name="ImageSection">
                <DataTemplate>
                    <local:MyImageUserControl x:Name="ImageControl"/>
                </DataTemplate>
             </HubSection>
          </Hub>      
       </Grid>
    </Page>
    void MainPage_Loaded(object sender, RoutedEventArgs e) {
       // Not possible. Elements within DataTemplate cannot be accessed...
       ListControl.DoSomething();
       ImageControl.DoSomethingDifferent();
    }

    Since the controls cannot be accessed directly I tried to traversed the VisualTree to find the controls manually:

    MyListUserControl listControl;
    MyImageUserControl imageControl;
    
    void MainPage_Loaded(object sender, RoutedEventArgs e) {
       FindControls(this);
    
       if (listControl != null)
          listControl.DoSomething();
    
       if (imageControl != null)
          imageControl.DoSomethingDifferent();
    }
    
    private void FindControls(DependencyObject parent) {
       for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) {
          DependencyObject child = VisualTreeHelper.GetChild(parent, i);
    
          if (child is MyListUserControl) {
             listControl = (child as MyListUserControl);
          } else if (child is MyImageUserControl) {
             imageControl= (child as MyImageUserControl);
          }
    
          if (listControl == null || imageControl == null)
             FindControl(child);
          else
             break;
       }
    }

    This does not work either, only the MyListUserControl is found. If I log the Child elements the VisualTree looks like this:

    ...
       13: Windows.UI.Xaml.Controls.Grid
          14: Windows.UI.Xaml.Controls.ScrollContentPresenter
             15: Windows.UI.Xaml.Controls.ItemsStackPanel
                16: Windows.UI.Xaml.Controls.HubSection
                   17: Windows.UI.Xaml.Controls.Border
                      18: Windows.UI.Xaml.Controls.Grid
                         19: Windows.UI.Xaml.Shapes.Rectangle
                         19: Windows.UI.Xaml.Controls.Button
                            20: ... 
                         19: Windows.UI.Xaml.Controls.ContentPresenter
                            20: MyListUserControl

    The ItemsStackPanel (15) has only one child, the first HubSection with the MyListUserControl in it. No other HubSection is found. At least this is what happens most of the time. It also happens that the first three sections are found. Even sometimes all sections are found.

    Thus there is nothing wrong with the search method or the XAML. It seems that the Hub does not load all Sections at once. So, how do I access the controls within the Sections?




    • Edited by Agenor Wednesday, March 26, 2014 11:16 AM
    Wednesday, March 26, 2014 11:03 AM

All replies

  • Assign a handler to the loaded event for each control inside a HubSection.  When it loads, hold a reference to it so you can use it when you need it.

    Not elegant, but it works.


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Wednesday, March 26, 2014 8:04 PM
    Moderator
  • Sure, the UserControls could use their Loaded-Event and notify the MainPage once loading is complete. But some of the UCs are not only used in the MainPage HubSections but on other pages as well. How to handle that instance A of the UC should notify the MainPage and instance B should not?

    Even if the UCs would only be used on the MainPage this solution would not work very well. It seems that the Hub does not load all Sections at once. Some are loaded earlier and some are loaded some time later. But all Sections should start some long running tasks as soon as the MainPage is loaded (e.g. fetch new images from a server) and not wait until the hub decided to eventually load a section.

    Is there a way to tell the hub to load all sections immediately?

    Thursday, March 27, 2014 7:51 AM