Question

I have a Panorama control which has three items:

<phone:Panorama>

    <phone:PanoramaItem>

    </phone:PanoramaItem>

    <phone:PanoramaItem>

    </phone:PanoramaItem>

    <phone:PanoramaItem Header="third item" Orientation="Horizontal">
        <Grid>
            <StackPanel Margin="0,4,16,0" Orientation="Vertical" VerticalAlignment="Top">
                <StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                </StackPanel>
                <StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Margin="0,12,0,0">
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="#FFFFC700" Height="173" Width="173" Margin="12,0,0,0"/>
                    <Border Background="Black" Height="173" Width="173" Margin="12,0,0,0"/>
                </StackPanel>
            </StackPanel>
        </Grid>
    </phone:PanoramaItem>
</phone:Panorama>

How can I know if last Border with black background is on screen and visible for user? because it is a horizontal PanoramaItem, I can't rely on SelectedIndex of panorama. any tips?

Was it helpful?

Solution

If you just want to check if an element is within the screen bounds you can use the VisualTreeHelper like this:

Rect screenBounds = new Rect(0, 0, Application.Current.Host.Content.ActualWidth, Application.Current.Host.Content.ActualHeight);

if (VisualTreeHelper.FindElementsInHostCoordinates(screenBounds, myPanorama).Contains(elementToCheck))
    Debug.WriteLine("Element is now visible");
else
    Debug.WriteLine("Element is no longer visible");

I made two changes to the XAML (just to simplify the example), first I named the Panorama:

<phone:Panorama x:Name="myPanorama">

And secondly I also named the Border element you want to check the visibility of:

<Border x:Name="elementToCheck" Background="Black" Height="173" Width="173" Margin="12,0,0,0"/>

If you also want to check it in an event when the Panorama scroll is changing it seems to get a bit harder, because the ManipulationDelta event does not work if a control is beneath other controls. One solution would be to check each time a fram is reported for touch. This is done in the following way:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    Touch.FrameReported += Touch_FrameReported;
}

private void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
    // This is the same code as above
    Rect screenBounds = new Rect(0, 0, Application.Current.Host.Content.ActualWidth, Application.Current.Host.Content.ActualHeight);

    if (VisualTreeHelper.FindElementsInHostCoordinates(screenBounds, myPanorama).Contains(elementToCheck))
        Debug.WriteLine("Element is now visible");
    else
        Debug.WriteLine("Element is no longer visible");
}

You will also need those two using directives for VisualTreeHelper and Touch:

using System.Windows.Media;
using System.Windows.Input;

Unfortunatly I couldn't think of an easier solution for this right now.

EDIT: This is far from perfect regarding the event, for example if the Panorama is "panned" programmatically or when it snaps it will not give the expected result. The problem is that the Panorama is built upon PanningLayer, PanningTitleLayer, PanningBackgroundLayer and not a ScrollViewer, so no ScrollBar, which means no Scroll event :(

One solution would be to use a timer to periodically check if it is visible, but that also feels like an ugly solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top