8

编辑:为避免混淆:这是关于以前称为或仍称为Microsoft Surface 1.0的表。这与以前称为Microsoft Surface 2.0的桌子无关,也与现在称为Microsoft Surface的平板电脑无关。编辑结束

我正在编写一个 WPF 应用程序,它既可以在桌面系统上运行,也可以在 MS Surface/PixelSense 1.0 上运行。我正在寻找有关通常如何完成的约定。

我知道平台之间存在一些差异,这就是为什么桌面版和 PixelSense 版本的基本 GUI 框架不同(在这种情况下,Canvas桌面版本ScatterView中的 a 和 PixelSense 版本中的 a 作为根 GUI 元素)。

但是,桌面版本中有许多基于 WPF 的用户控件/GUI 片段在 PixelSense 版本中的显示方式应该或多或少相同。

不幸的是,标准的 WPF 控件似乎在 PixelSense 中不起作用。为了对用户输入做出反应,CheckBox必须替换控件等控件,可以通过 PixelSense 上的这个小代码示例轻松验证:SurfaceCheckBox

var item = new ScatterViewItem();
var sp = new StackPanel();
item.Content = sp;
item.Padding = new Thickness(20);
sp.Children.Add(new CheckBox() { Content = "CheckBox" });
sp.Children.Add(new SurfaceCheckBox() { Content = "SurfaceCheckBox" });
myScatterView.Items.Add(item);

显然,这意味着 WPF 用户控件无法在没有任何更改的情况下显示在 PixelSense 上,正如Microsoft 在 PixelSense 表示层上的文档等资源中的声明所证实的那样,诸如与 WPF 树视图相关的这个问题也提到了到,这篇关于 PixelSense WPF 层的博文这个关于如何为 PixelSense 重写 WPF 桌面应用程序的 SO 问题。后一页甚至将所需的更改称为最小更改,但它们仍然是更改。

此外,对如何在 PixelSense 上使用特定 WPF 桌面控件的这个 SO 问题的反应意味着使用 .NET 4.0 可能会简化事情,但我认为 PixelSense 1.0 SDK 不支持 .NET 4.0(它是 .NET 3.5 -据我所知)。

作为一名软件工程师,我仍然不能同意使用相同的编程语言两次编写相同的 GUI 片段(包括在相同布局中具有相同数据模型行为的基本相同控件)的策略。这似乎是错误的。

因此,到目前为止,我发现了三种可能的解决方案:

  • 为标准 WPF 编写 GUI 片段。然后使用脚本复制包含这些 GUI 片段的库,同时转换所有相关的 Xaml 文件(例如,使用 XSLT)以将标准 WPF 控件替换为Surface*对应的控件。
    缺点:
    • 每当 WPF 项目中的某些内容发生更改时,始终保持脚本正常工作和运行它们需要增加维护。
    • 此外,定义要考虑的 Xaml 文件以及要替换的控件(想想额外的第 3 方 PixelSense 控件......)可能最终会变得复杂。
    • 最后,生成的 PixelSense-Project 将是 WPF 项目的精确副本,除了 Xaml 文件,因此不能引入特定于 PixelSense 的代码(或者如果可以,这将使生成 PixelSense 项目的脚本更多复杂的)。
  • 仅针对 PixelSense/Surface,并让桌面用户安装 Surface SDK。感谢用户Clemens的建议!
    缺点:
    • 用户必须安装Surface 1.0 SDK,这在当前系统上是一项非常重要的操作:为了让Surface 1.0 SDK在 Windows 7 64 位机器上运行,必须执行各种操作,例如修补 MSI 文件。
    • PixelSense/Surface 1.0 模拟器是在台式计算机上运行 Surface 1.0 应用程序的唯一可能性。这个模拟器不是很好用,而且在某些系统上完全是错误的:在我的电脑上,它看起来像这样:(越野车 Surface 1.0 模拟器输出只覆盖了模拟器窗口的 3/4,但输入在整个窗口中注册。即单击 Surface 模拟的右下角,我必须单击模拟器窗口的(显然是透明的)右下角。)
  • 创建 GUI 时,不要显式使用标准 WPF 或 PixelSense 控件类,而是使用特定于平台的工厂来创建适当的控件类型。
    缺点:
    • GUI 片段不能再用 Xaml 编写;至少大多数控件及其所有绑定都必须在 C# 代码中创建。

我目前倾向于第三种选择,因为独立于平台似乎是一个可以接受的价格。然而,我认为 WPF 是桌面和 PixelSense GUI 之间的连接元素,这应该是一个经常出现的问题,我想知道这是否以前没有解决过。所以,我在这里问:这通常是怎么做的?

PS:方向不是问题。上述 GUI 片段显示在 PixelSense 上的可旋转 ScatterViewItems 中,并在桌面上以正常的垂直方向显示。

4

1 回答 1

7

让我们从回到 Surface 1.0 构建时的机器开始……

时间是2006年,Windows操作系统(甚至主流手机!)都没有多点触控的概念。没有 API 允许应用程序响应同时与多个控件交互的用户。现有 UI 框架中内置的输入路由、捕获和聚焦机制基本上都禁止多点触控以非蹩脚的方式工作。即使这些问题神奇地消失了,大多数应用程序仍然会在用户执行他们无法处理的事情时崩溃(例如同时单击“保存”和“退出”按钮),并且用户会非常暴躁,因为外观和现有应用程序/控件的感觉针对微小的鼠标光标而不是粗大的手指进行了优化。

因此,在 2006 年,我带领 Surface 团队在 WPF 之上创建了一个抽象层来解决所有这些问题……结果就是您所询问的 1.0 SDK。我们试图通过子类化现有 UI 控件而不是创建全新的层次结构来最小化您提到的软件工程问题(这个决定使开发 SDK变得更加困难)所以虽然您必须在每个平台上使用实例化不同的类,但在那之后在原始版本的控件中使用的事件和属性将按预期在 Surface 版本中工作。

快进到 2009 年……多点触控开始流行起来。Windows 7 添加了对多点触控的原生支持,但并未真正解决 UI 框架问题。

快进到 2010 年... WPF 和 Surface 团队合作采用 Surface 针对我列出的问题构建的许多解决方案,使它们适应 Win7 的本机触控堆栈,并将它们作为 WPF 4.0 的内置部分提供。 .. 这提供了多点触控输入路由、事件、捕获和焦点,但触控功能不能简单地添加到内置 WPF 控件中而不破坏大量现有应用程序。因此,Surface 团队发布了“Surface Toolkit for Windows Touch”,它提供了大多数 Surface 1.0 UI 控件的 WPF 4.0 兼容版本。但是 2006 年的 Surface 1.0 与这个新版本的 WPF 不兼容,因此虽然您最终可以为 Windows 和 Surface 构建杀手级触控体验,但您仍然无法 100% 共享您的代码。

快进到 2011... Surface 2.0(使用 PixelSense 技术的版本)发布。它使用新的 WPF 4.0 功能(不再需要 Surface 1 SDK 附带的许多 API),并包括本质上是适用于 Windows 的 Surface Toolkit 的更新版本,尽管现在控件已重新设计为地铁。最后,产品时间线已同步,您可以使用单个代码库为两个平台构建出色的触控体验。

好的,现在回到你现在的问题……你问的是 Surface 1.0,所以 2011 年的精彩并不能真正帮助你。不过,您可以利用 2010 年的东西:

  1. 使用 WPF 4 API 和 Surface Toolkit for Windows Touch 构建您的应用程序
  2. 编写一些代码来获取 Surface 输入事件并通过 WPF 4 的输入堆栈对其进行路由(执行此操作的能力不是很广为人知,但它是专门为这种类型的场景创建的)。

那么你是怎么做这些事情的呢?好问题。幸运的是,我的好友 Joshua Blake 有一篇博客文章以及一些可重用的代码来引导您完成它。看看http://nui.joshland.org/2010/07/sharing-binaries-between-surface-and.html

于 2012-06-29T13:29:47.317 回答