WPF和Silverlight控件及布局的平移和缩放功能

6
我想了解实现平移和缩放(拖动和缩放)功能的WPF / Silverlight布局的一般要求。我不是指图像的平移和缩放,而是指整个页面(窗口)布局(或其中一部分)以及某些控件。
布局的哪些特征以及使用的自定义控件的哪些特征会使布局固定且无法进行平移和缩放?
4个回答

10

通用规则

除了极少数情况外,WPF 中的所有内容都可以随意平移、缩放、旋转、拉伸等。这包括单个控件(如 Button)、复合控件(如 ListBox)和容器(如 StackPanel)。

特殊情况

以下是特殊情况:

  1. 如果您正在使用 Adorner,并且您的 AdornerDecorator 在已平移/缩放的区域之外,则附加到已平移/缩放区域的 Adorners 将进行平移但不会缩放。解决方法是在已平移/缩放区域内添加一个额外的 AdornerDecorator。

  2. 如果您使用 Popup,则它将显示在其 PlacementTarget 的已平移/缩放位置,但它本身不会缩放。当您平移包含其 PlacementTarget 的区域时,它也不会移动(基本上它坐在自己的表面上方)。要解决此问题,请在需要在缩放/平移区域中弹出某些内容时使用零大小 Canvas 和高 Z 顺序。

  3. 您定义的任何 ContextMenu 都将显示在弹出窗口中,因此即使单击的区域缩放或放大,菜单项也将以正常大小显示。由于上下文菜单的性质,这可能是期望的行为。如果不是,您可以将菜单项包装在 ViewBox 中,并将缩放与主区域的缩放绑定。

  4. 您的 ToolTips 将以正常大小显示,即使 UI 被平移或缩放。解决方案与 ContextMenu 相同。

  5. 如果您使用 WinForms 集成来集成旧版 WinForms 控件和 UI,则它们在某些情况下将无法正常平移、缩放和裁剪。有一种高级技术可解决此问题,即将 WinForms 控件在屏幕外实现,然后使用 BitBlt 或类似的方法将图像复制到窗口中作为图像,并将鼠标点击和按键操作转发到屏幕外窗口。但这需要大量工作。

  • 如果绕过WPF直接使用GDI+或DirectX,或者使用Win32 hWnds显示内容或UI,则该内容或UI将不会正确地滚动、缩放或剪切到窗口,除非在您的接口代码中自己完成。

  • 最后注意事项

    • 一个好的WPF UI总是使用诸如Grid、DockPanel等面板来以灵活的方式布置控件,使它们自动适应容器大小,而不是使用固定的大小和位置。这也适用于您的 pan/zoom 区域的内部内容,但是有一个例外:您的 pan/zoom 区域中的最外层元素必须具有指定的大小。否则,什么来定义被平移/缩放的区域呢?

    • 实现平移/缩放功能的简单方法是调整 pan/zoom 区域中最外层控件的 RenderTransform。可以使用许多不同的方式来实现平移和缩放的控件,例如可以使用工具栏按钮和滑块、滚动条、鼠标滚轮、空格键+拖动进行平移,被平移 UI 本身的可拖动区域,或以上任意组合。无论您选择哪种界面,只需从代码后台适当地更新 RenderTransform,您就可以开始工作了。

    • 如果您选择的平移机制是滚动条,则可能希望使用 ScrollViewer 并仅使用 RenderTransform 进行缩放。

    • 请确保在 pan/zoom 区域上设置剪辑。否则,如果您缩放或平移超出边界的项目,它们仍将在 pan/zoom 区域外可见。


    Ray,感谢您花费时间和精力给出如此详细的答案。+1 - rem
    有一种高级技术可以解决这个问题,即在屏幕外实现WinForms控件,然后使用BitBlt或类似的方法将图像作为图像复制到您的窗口中,并将鼠标点击和按键转发到屏幕外窗口。不过,这需要很多工作。你有任何人已经做过这个的参考吗?特别是事件转发机制似乎很棘手。 - Russell Mull
    @Russell:我曾经尝试过一些能够实现这个功能的代码,但是那不是我自己写的,而且我也不知道在哪里可以找到类似的示例。我记得事件转发代码发布了一些简单的低级WM_消息,例如WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_KEYDOWN等。 - Ray Burns

    3

    使用MultiScaleImage或Canvas区域,将需要平移和缩放的所有内容放置其中

    <Canvas x:Name="panZoomPanel" Background="Transparent">
    </Canvas>
    

    在编程中使用TransformGroup、TranslateTransform和ScaleTransform进行平移和缩放。
    查看其他SO postexamplethis one

    2
    通常,您可以将任何复合UI元素集视为单个UIElement来处理,因此图像的情况与对整个应用程序执行相同操作并没有真正不同。基于用户输入处理缩放的最佳方法(而不是Viewbox执行自动缩放)是应用ScaleTransform。这可以设置在高级父元素上,例如窗口布局的根处的Grid上。对于平移,您可以组合TranslateTransform,或在某些情况下使用ScrollViewer来处理移动内容的视图。

    1

    在XAML中实现缩放的一种非常简单的方法是使用Silverlight ViewBox。这将缩放XAML而不是像素。您可以指定要使用的拉伸方式,ViewBox将根据此进行缩放(填充、无、均匀等)。如果您在Google上搜索Silverlight+Viewbox,就会发现一些很棒的Viewbox博客文章。

    通过类似于拖放的机制轻松实现平移,并且还有许多如何博客文章可供参考,可以通过Google获得。只需捕获MouseDown、MouseMove和MouseUp事件即可。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接