Windows Phone 8.1. Toggle Visibility of TextBlock in DataTemplate

I am creating a Windows Phone 8.1 Hub Application. One of the hub sections contains a ListView that displays a list of articles. I would like to add a Textblock to this hubsection that displays a message when articles are not loading. The XAML code is below:

<HubSection 
    x:Uid="ArticlesSection" 
    Header="ARTICLES" 
    DataContext="{Binding Articles}" 
    HeaderTemplate="{ThemeResource HubSectionHeaderTemplate}">
    <DataTemplate>
        <Grid>
            <ListView 
                AutomationProperties.AutomationId="ItemListViewSection3"
                AutomationProperties.Name="Items In Group"
                SelectionMode="None"
                IsItemClickEnabled="True"
                ItemsSource="{Binding}"
                ItemTemplate="{StaticResource BannerBackgroundArticleTemplate}"
                ItemClick="ItemView_ItemClick"
                ContinuumNavigationTransitionInfo.ExitElementContainer="True">
            </ListView>
            <TextBlock 
                x:Name="NoArticlesTextBlock" 
                HorizontalAlignment="Center" 
                VerticalAlignment="center" 
                Style="{StaticResource HeaderTextBlockStyle}" 
                TextWrapping="WrapWholeWords" 
                TextAlignment="Center"/>
        </Grid>
    </DataTemplate>
</HubSection>

      

The problem I am facing is that I cannot access the TextBlock from the C # code. Is there an easier way to do this?

+3


source to share


1 answer


The problem I am facing is that I cannot access the TextBlock from the C # code.

Yes, since the TextBlock is defined inside the DataTemplate, the TextBlock will not be available until the DataTemplate is applied. So the x: Name attribute will not automatically generate a variable reference in the InitializeComponent method in your * .gics file. (Read the XAML Namescopes for more details ).

If you want to access it from code, there are two ways:

The first way is the simplest: you can get a reference to the TextBlock in the sender argument of the Loaded event handler for that TextBlock.

<TextBlock Loaded="NoArticlesTextBlock_Loaded" />

      

Then in code:

private TextBlock NoArticlesTextBlock;

private void NoArticlesTextBlock_Loaded(object sender, RoutedEventArgs e)
{
    NoArticlesTextBlock = (TextBlock)sender;
}

      




The second way is to traverse the visual tree manually to find the element with the required name. This is more suitable for dynamic layouts, or when you have a lot of controls that you want to reference in the way that the previous way would be too confusing. You can achieve this in the following way:

<Page Loaded="Page_Loaded" ... />

      

Then in code:

static DependencyObject FindChildByName(DependencyObject from, string name)
{
    int count = VisualTreeHelper.GetChildrenCount(from);

    for (int i = 0; i < count; i++)
    {
        var child = VisualTreeHelper.GetChild(from, i);
        if (child is FrameworkElement && ((FrameworkElement)child).Name == name)
            return child;

        var result = FindChildByName(child, name);
        if (result != null)
            return result;
    }

    return null;
}

private TextBlock NoArticlesTextBlock;

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    // Note: No need to start searching from the root (this), we can just start
    // from the relevant HubSection or whatever. Make sure your TextBlock has
    // x:Name="NoArticlesTextBlock" attribute in the XAML.
    NoArticlesTextBlock = (TextBlock)FindChildByName(this, "NoArticlesTextBlock");
}

      


Jerry Nixon has a nice page on his blog about this.

+10


source







All Articles