How to access controls within HubSections in Win 8

2020-07-22 10:08发布

问题:

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 - as proposed in answers to similar questions:

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?

回答1:

You can use the Loaded event of your own controls and the sender parameter will be the control you are looking for.

<local:MyListUserControl x:Name="ListControl" Loaded="ListControl_Loaded"/>

Then in the code:

private void ListControl_Loaded(object sender, RoutedEventArgs e)
{
     listControl = (MyListUserControl)sender;
}

And you can do the same for your ImageControl as well.