如何在窗口大小更改时动态测量 WPF 中的网格宽度/高度

本文关键字:网格 高度 WPF 测量 窗口大小 动态 | 更新日期: 2023-09-27 17:57:52

总的来说,我想做的是在画布上添加一个椭圆,以表示高尔夫球在圆周上的位置,当高尔夫球推杆从圆的中心以一定角度击打时。为此,我使用了两个图像,一个是分成几部分的圆圈,以表示球被击中的角度。另一个图像只是一个推杆头,它被旋转以代表球杆击球的角度。此图像位于圆形图像的顶部。蓝色椭圆表示球的位置。在下面的链接中查看从我的应用程序获得的图像输出:

所需的应用程序输出

为此,我基本上使用以下代码计算了网格的宽度和高度:

public FacePage()
{
    InitializeComponent();
    GridGraphs.SizeChanged += GridGraphs_SizeChanged;
}
void GridGraphs_SizeChanged(object sender, SizeChangedEventArgs e)
{
    GetMeasurements();
}
private void GetMeasurements()
{
    GridGraphs.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    double width = GridGraphs.DesiredSize.Width;
    double height = GridGraphs.DesiredSize.Height;
    RotatePutter(width, height);
}

然后将宽度和高度传递到 RotatePutter(( 中,其中宽度和高度除以 2 以获得网格的中心点,如下所示:

public void RotatePutter(double width, double height)
{
    double radius = width * 0.5;
    double centerX = width * 0.5;
    double centerY = height * 0.5;
    Random ran = new Random();
    double angle = ran.Next(-15, 15);
    if (angle >= 0)
    {
        if (angle <= 5)
        {
            lblShotStaus.Content = "Square";
        }
        else
        {
            lblShotStaus.Content = "Open";
        }
    }
    else
    {
        lblShotStaus.Content = "Closed";
    }
    double angleradians = (angle * (Math.PI / 180));
    Point putterCentre = new Point(0.5, 0.5);
    imgPutter.RenderTransformOrigin = putterCentre;
    RotateTransform rt = new RotateTransform(angle, 0.5, 0.5);
    imgPutter.RenderTransform = rt;
    BallLocation(radius, angleradians, centerX, centerY);
}
中心点,半径,角度和

推杆图像在这里旋转,半径,角度弧度,中心X和中心Y被传递给BallLocation以计算球的位置,如下所示:

public void BallLocation(double rad, double anglerad, double centerX, double centerY)
{
    Ellipse ellipse = new Ellipse();
    double xBallPoint = (centerX - (rad * Math.Cos(anglerad)));
    double yBallPoint = (centerY - (rad * Math.Sin(anglerad)));
    ellipse.Height = 10;
    ellipse.Width = 10;
    ellipse.Fill = new SolidColorBrush(Colors.Aqua);
    Canvas.SetLeft(ellipse, xBallPoint);
    Canvas.SetTop(ellipse, yBallPoint);
    canvasFaceAngle.Children.Add(ellipse);
}

这在全屏模式下工作正常,一旦我更改窗口的大小,球被击中的角度的位置都是错误的。

有谁知道如何在窗口大小变化时动态获取网格宽度和高度,以便计算椭圆(球(的正确位置。或者任何其他完成此操作的替代方法也受到欢迎。提前谢谢。

这是我的 xaml:

<UserControl x:Class="HoleMorePuttsApplication.Pages.FacePage"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="40*"/>
        <ColumnDefinition Width="60*"/>
    </Grid.ColumnDefinitions>
    <Viewbox Grid.ColumnSpan="1">
        <Label Content="Face Angle Page" FontWeight="Bold" />
    </Viewbox>
    <Grid Name="GridGraphs" Column="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Name="columnLeft" Width="50*"/>
            <ColumnDefinition Name="columnRight" Width="50*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Name="rowTop" Height="70*"/>
            <RowDefinition Name="rowBottom" Height="30*"/>
        </Grid.RowDefinitions>
        <Image x:Name="imgAngles"  Source="C:'Users'BernardWork'Documents'Work'Net'PuttingApp'Images'360Angles.jpg" Grid.ColumnSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"/>
        <Image x:Name="imgPutter"   Source="C:'Users'BernardWork'Documents'Work'Net'PuttingApp'Images'Putter.jpg" Opacity="0.5" Margin="130,105,70,105" Grid.ColumnSpan="2" HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
        <Label x:Name="lblShotStaus" Content="Label" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
        <Canvas Name="canvasFaceAngle" Grid.ColumnSpan="2" Grid.Row="0" RenderTransformOrigin="0.543,0.511"></Canvas>

    </Grid>
</Grid>

如何在窗口大小更改时动态测量 WPF 中的网格宽度/高度

如果我理解正确,我相信问题可能出在:

double width = GridGraphs.DesiredSize.Width;
double height = GridGraphs.DesiredSize.Height;

您调用 Measure 时没有提供任何限制,这意味着它会告诉您如果没有限制(因此,DesiredSize(Grid的大小。 DesiredSizeActualSize可能是两个非常不同的值。

在上面的情况下,SizeChanged方法的参数将为您提供所需的内容。

void GridGraphs_SizeChanged(object sender, SizeChangedEventArgs e)
{
    RotatePutter(e.NewSize.Width, e.NewSize.Height);
}

因此,如果目标只是获取网格宽度/高度,则 ActualWidthActualHeight 属性应该为您提供该信息。但有一点需要注意:虽然 Grid 控件会随窗口一起更改大小,但 Canvas 控件不会。换句话说,如果您读取网格的实际宽度/高度,它应该对应于窗口的一侧,但如果您读取画布的实际宽度/高度,它可能会为您提供不正确的信息。