【问题标题】:How can I get WPF's ClipToBounds to work?如何让 WPF 的 ClipToBounds 工作?
【发布时间】:2011-10-04 19:43:38
【问题描述】:

我有一个在 WPF 中的 Image 对象内显示图像的应用程序。该图像包含在一个控件中,其 xaml 如下所示:

<UserControl x:Class="MyProgram.NativeImageDisplay"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Loaded="UserControl_Loaded">
    <Canvas Name="border" Background="Black" >
        <Image Name="image" StretchDirection="Both" Stretch="Uniform" ClipToBounds="True"
                SnapsToDevicePixels="True" RenderOptions.BitmapScalingMode="HighQuality"></Image>
    </Canvas>
</UserControl>

其中两个控件包含在窗口的网格中,如下所示:

    <Grid  Grid.Row="2" Name="DisplayCanvas">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <l:NativeImageDisplay x:Name="imageDisplay2" Grid.Column="1" ClipToBounds="True"/>
        <l:NativeImageDisplay x:Name="imageDisplay" Grid.Column="0" ClipToBounds="True"/>           
    </Grid>

我一直在说剪辑是真的。

用户可以使用鼠标上的滚动按钮来放大图像,并最终在图像上调用 ScaleTransform:

    private void image_MouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (!thumbnail)
        {
            TransformGroup transformGroup = (TransformGroup)border.RenderTransform;
            ScaleTransform transform = (ScaleTransform)transformGroup.Children[0];

            double oldScaleX = transform.ScaleX;
            double oldScaleY = transform.ScaleY;

            double zoom = e.Delta;
            transform.ScaleX += zoom / 10000;
            transform.ScaleY += zoom / 10000;
            if (transform.ScaleX > maxZoom || transform.ScaleY > maxZoom)
            {
                transform.ScaleX = maxZoom;
                transform.ScaleY = maxZoom;
            }
            if (transform.ScaleX < minZoom || transform.ScaleY < minZoom)
            {
                transform.ScaleX = minZoom;
                transform.ScaleY = minZoom;
            }
            Point thePoint = e.GetPosition(border);
            transform.CenterY = 0;
            transform.CenterX = 0;

            foreach (UIElement child in border.Children)
            {
                if (child is Anchor)
                {
                    TransformGroup group = (TransformGroup)child.RenderTransform;
                    ScaleTransform t = (ScaleTransform)group.Children[0];
                    t.ScaleX *= oldScaleX / transform.ScaleX;
                    t.ScaleY *= oldScaleY / transform.ScaleY;
                }
            }
        }
    }

一旦调用了缩放变换,图像就不再包含在其画布的边界或网格选择中。本质上, ClipToBounds 被忽略了。如何让这个变换关注 ClipToBounds?

【问题讨论】:

    标签: wpf cliptobounds


    【解决方案1】:

    Canvas 的独特之处在于它不像其他元素那样真正参与布局系统。它基本上充当具有固定位置子级的无限大小的空间,因此通常完全忽略剪辑。如果没有看到更多代码,我无法确定,但如果你想将剪裁应用到缩放的对象,将缩放移动到不同的元素可能会做你想做的事。最简单的做法是在 Canvas 周围包裹一个 Border,然后将 ScaleTransform 应用到它上面。边框应该给你更好的剪裁行为。

    <Border x:Name="border" Background="Black" ClipToBounds="True">
        <Canvas x:Name="imageHost">
        ...
        </Canvas>
    </Border>
    

    【讨论】:

    • 被缩放的画布也可以包含在第二个画布中,在外部画布上具有 ClipToBounds="True"。
    【解决方案2】:

    上面的评论帮助我。将一个画布嵌套在另一个画布中,将ClipToBounds="True" 添加到父级,并将嵌套的高度和宽度分别绑定到父级属性。
    这种方式消除了对父级执行转换的需要。

    <Canvas ClipToBounds="True" Name="Outer">
         <Canvas x:Name="Inner" 
             Height="{Binding ActualHeight, ElementName=Outer, Mode=OneWay}"
             Width="{Binding ActualWidth, ElementName=Outer, Mode=OneWay}" />
    </Canvas>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      相关资源
      最近更新 更多