Is it possible for a WPF control to have an Actual

2019-02-14 03:32发布

问题:

I need a Viewport3D for the sole purpose of doing geometric calculations using Petzold.Media3D.ViewportInfo. I would prefer not to have to place it in a Window or otherwise render it.

I'm attempting to accomplish this by instantiating a Viewport3D and setting a few properties using the following C# method:

private Viewport3D CreateViewport(MainSettings settings)
{
    var cameraPosition = new Point3D(0, 0, settings.CameraHeight);
    var cameraLookDirection = new Vector3D(0, 0, -1);
    var cameraUpDirection = new Vector3D(0, 1, 0);
    var camera = new PerspectiveCamera
    {
        Position = cameraPosition,
        LookDirection = cameraLookDirection,
        UpDirection = cameraUpDirection
    };
    var viewport = new Viewport3D
    {
        Camera = camera,
        Width = settings.ViewportWidth,
        Height = settings.ViewportHeight
    };
    return viewport;
}

Later, I'm attempting to use this viewport to convert the mouse location to a 3D location using this method:

public Point3D? Point2dToPoint3d(Point point)
{
    var range = new LineRange();
    var isValid = ViewportInfo.Point2DtoPoint3D(_viewport, point, out range);
    if (isValid)
        return range.PointFromZ(0);
    else
        return null;
}

Unfortunately, it's not working. I think the reason is that the ActualWidth and ActualHeight of the viewport are both zero (and these are read-only properties, so I can't set them manually). (Note: I have tested the exact same method with an actual rendered Viewport3D, and it worked fine, so I know the issue is not with my converter method.)

Any idea how I can get WPF to assign the ActualWidth and ActualHeight of a control based on the Width and Height settings?

I tried setting the HorizontalAlignment and VerticalAlignment to Left and Top, respectively, and I also messed with the MinWidth and MinHeight, but none of these properties had any effect on the ActualWidth or ActualHeight.

回答1:

From MSDN topic for the ActualWidth property:

This property is a calculated value based on other width inputs, and the layout system. The value is set by the layout system itself, based on an actual rendering pass, and may therefore lag slightly behind the set value of properties such as Width that are the basis of the input change.

So, this sounds like a rendering pass is necessary for the property to be set. However, you could try to call Measure(Size) and then Arrange(Rect) to simulate the layout process. Maybe this is already sufficient.