You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Viewbox嵌套Canvas,运行时无法通过ActualWidth/ActualHeight获取真实尺寸

解决Viewbox内Canvas真实宽高获取问题

问题核心是Viewbox对Canvas的缩放是通过渲染变换(RenderTransform)实现的,而Canvas的ActualWidth/ActualHeight只会返回你设置的固定值,不会自动计算缩放后的尺寸。要拿到真实显示的宽高,有两种常用方法:

方法1:计算缩放因子后换算

Viewbox内部会维护一个缩放比例,你可以通过Viewbox.ActualWidth和它的子元素(外层Canvas)的原始宽度算出缩放比例,再用这个比例乘以内部Canvas的尺寸:

修改后台代码如下:

private void Button_Click(object sender, RoutedEventArgs e)
{
    // 获取外层Viewbox
    var viewbox = innerCanvas.Parent.Parent as Viewbox;
    if (viewbox == null) return;
    
    // 获取外层Canvas的原始尺寸
    var outerCanvas = viewbox.Child as Canvas;
    if (outerCanvas == null) return;
    
    // 计算缩放比例(Viewbox会保持宽高比,取最小的那个比例)
    double scaleX = viewbox.ActualWidth / outerCanvas.Width;
    double scaleY = viewbox.ActualHeight / outerCanvas.Height;
    double scale = Math.Min(scaleX, scaleY);
    
    // 计算内部Canvas的真实显示尺寸
    double realWidth = innerCanvas.Width * scale;
    double realHeight = innerCanvas.Height * scale;
    
    MessageBox.Show($"真实宽: {realWidth:F2}, 真实高: {realHeight:F2}");
}

方法2:改用LayoutTransform实现缩放(场景允许时)

如果你的布局可以调整,把Viewbox换成给外层Canvas添加LayoutTransform的方式,这样Canvas的ActualWidth/ActualHeight会直接反映缩放后的尺寸:

修改XAML:

<Window 
    ...
    Title="MainWindow" Height="450" Width="800" SizeChanged="Window_SizeChanged">
    <Grid>
        <Canvas Width="500" Height="300" Background="Red">
            <Canvas.LayoutTransform>
                <ScaleTransform x:Name="canvasScale"/>
            </Canvas.LayoutTransform>
            <Canvas Width="200" Height="200" Background="Green" Name="innerCanvas">
            </Canvas>
        </Canvas>
        <Button Click="Button_Click" Height="30" VerticalAlignment="Bottom" Content="Click"></Button>
    </Grid>
</Window>

添加窗口尺寸变化事件和按钮点击事件代码:

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
    var outerCanvas = innerCanvas.Parent as Canvas;
    if (outerCanvas == null) return;
    
    double scaleX = e.NewSize.Width / outerCanvas.Width;
    double scaleY = e.NewSize.Height / outerCanvas.Height;
    double scale = Math.Min(scaleX, scaleY);
    
    canvasScale.ScaleX = scale;
    canvasScale.ScaleY = scale;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show($"真实宽: {innerCanvas.ActualWidth:F2}, 真实高: {innerCanvas.ActualHeight:F2}");
}

内容的提问来源于stack exchange,提问作者Nehorai Raphael Elbaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 18:54:20