在PivotItem中查找UIElement的真实位置

时间:2014-08-18 17:05:20

标签: silverlight xaml windows-phone-7 windows-phone-8 windows-phone

我希望获得嵌入TextBlock的{​​{1}}的屏幕位置和可见性 - 例如PivotItem的屏幕位置和可见性:

TB2

对于其他Xaml控件,我使用以下代码实现了这一点:

    <phone:Pivot>
        <phone:PivotItem Header="first">
            <TextBlock x:Name="TB1" Text="Hello 1"></TextBlock>
        </phone:PivotItem>

        <phone:PivotItem Header="second" >
            <TextBlock x:Name="TB2" Text="Hello 2"></TextBlock>
        </phone:PivotItem>

        <phone:PivotItem Header="three" >
            <TextBlock x:Name="TB3" Text="Hello 3"></TextBlock>
        </phone:PivotItem>
    </phone:Pivot>

但是,对于 public static Rect Position(this FrameworkElement element) { if (element.Visibility == Visibility.Collapsed) return Rect.Empty; if (element.Opacity < 0.01) return Rect.Empty; // Obtain transform information based off root element GeneralTransform gt = element.TransformToVisual(Application.Current.RootVisual); // Find the four corners of the element Point topLeft = gt.Transform(new Point(0, 0)); Point topRight = gt.Transform(new Point(element.RenderSize.Width, 0)); Point bottomLeft = gt.Transform(new Point(0, element.RenderSize.Height)); Point bottomRight = gt.Transform(new Point(element.RenderSize.Width, element.RenderSize.Height)); var left = Math.Min(Math.Min(Math.Min(topLeft.X, topRight.X), bottomLeft.X), bottomRight.X); var top = Math.Min(Math.Min(Math.Min(topLeft.Y, topRight.Y), bottomLeft.Y), bottomRight.Y); var position = new Rect(left, top, element.ActualWidth, element.ActualHeight); return position; } 子项,当PivotItem在屏幕外时,此计算不会提供预期的答案。相反,它会在屏幕上向后滑动PivotItem时提供项目在屏幕上显示的位置的答案。在转换过程中,我可以看到使用上述方法正确计算位置 - 例如在转换过程中,我会看到位置从屏幕的左/右正确滑动。

我查看了其他属性,例如PivotItemVisible,看看这里是否有其他机制用于隐藏屏幕外的PivotItem或其中一个OpacityParent等等 - 但所有这些似乎都会产生GrandParentVisible个结果。

我还尝试迭代VisualTree,看看是否有任何具有纯色背景的元素屏蔽了“屏幕外”Opacity == 1.0 - 但我在树中看不到任何元素。

这里还有其他一些属性需要考虑吗? PivotItem内容在“屏幕外”时是如何隐藏的?如果我真的需要,我知道我可以使用PivotItem的{​​{1}}属性来尝试帮助进行SelectedIndex位置计算,但我希望避免{{1}如果可以的话 - 如果可能的话,我更愿意使用通用的Xaml和VisualTree方法来获得这个位置。

2 个答案:

答案 0 :(得分:1)

我调查了一下,但我找不到他们是如何隐藏PivotItems的。我猜这个位置是正确的,但是这个项目并不是因为未知(对我而言)的原因。稍后我会再次研究它,但是现在我想提一些我注意到的其他潜在问题。

  1. 你不应该在右下角使用Math.Max吗?原因是 - ActualHeight和ActualWidth不是旋转感知的。

  2. RenderSize.Width / Height和ActualWidth / Height不同。我不确定将它们用于计算是个好主意。

  3. 您是否需要检查元素上方可视树中的所有内容,以确定它是否实际可见?

  4. 编辑:我查看了Microsoft.Phone.dll的反编译源(这是带有Pivot控件的dll),我找不到任何关于如何隐藏PivotItem的内容。但是有一些本机方法调用。

答案 1 :(得分:0)

我对您的代码做了一些更改,并给出了UIElement的真实位置

XAML:

 <Grid x:Name="LayoutRoot" Background="Transparent">
        <!--Pivot Control-->
        <phone:Pivot x:Name="MyPivot">
            <phone:PivotItem Header="first" x:Name="first">
                <TextBlock x:Name="TB1" FontSize="30" Text="Hello 1" Tap="TB1_Tap"></TextBlock>
            </phone:PivotItem>

            <phone:PivotItem Header="second" x:Name="second">
                <TextBlock x:Name="TB2" FontSize="50" Height="66" Width="155" Margin="20" Text="Hello 2" Tap="TB2_Tap"></TextBlock>
            </phone:PivotItem>

            <phone:PivotItem Header="three" x:Name="three">
                <TextBlock x:Name="TB3" Text="Hello 3"></TextBlock>
            </phone:PivotItem>
        </phone:Pivot>
    </Grid>

CS:

public partial class PivotPage1 : PhoneApplicationPage

{
    public PivotPage1()
    {
        InitializeComponent();
    }
    private void TB1_Tap(object sender, System.Windows.Input.GestureEventArgs e)
    {
        Rect r = Pos.MyPosition(TB1,first);
        string str = "Left" + r.Left.ToString() + "\nTop:" + r.Top.ToString() + "\nRight:" + r.Right.ToString() + "\nBottom:" + r.Bottom.ToString() + "\nHeight:" + r.Height.ToString() + "\nWidth" + r.Width.ToString();
        MessageBox.Show(str);
    }

    private void TB2_Tap(object sender, System.Windows.Input.GestureEventArgs e)
    {
        Rect r = Pos.MyPosition(TB2,second);
        string str = "Left" + r.Left.ToString() + "\nTop:" + r.Top.ToString() + "\nRight:" + r.Right.ToString() + "\nBottom:" + r.Bottom.ToString() + "\nHeight:" + r.Height.ToString() + "\nWidth" + r.Width.ToString();
        MessageBox.Show(str);
    }
}

public static class Pos
{
    public static Rect MyPosition(FrameworkElement child,FrameworkElement parent)
    {
        if (child.Visibility == Visibility.Collapsed)
            return Rect.Empty;

    if (child.Opacity < 0.01)
        return Rect.Empty;

    // Obtain transform information based off root child
    GeneralTransform gt = child.TransformToVisual(parent);

    // Find the four corners of the child
    Point topLeft = gt.Transform(new Point(0, 0));
    Point topRight = gt.Transform(new Point(child.RenderSize.Width, 0));
    Point bottomLeft = gt.Transform(new Point(0, child.RenderSize.Height));
    Point bottomRight = gt.Transform(new Point(child.RenderSize.Width, child.RenderSize.Height));

    var left = Math.Min(Math.Min(Math.Min(topLeft.X, topRight.X), bottomLeft.X), bottomRight.X);
    var top = Math.Min(Math.Min(Math.Min(topLeft.Y, topRight.Y), bottomLeft.Y), bottomRight.Y);
    var position = new Rect(left, top, child.ActualWidth, child.ActualHeight);

    return position;
    }
}

Sample Screen Capture 1 Sample Screen Capture 2