c# - 在桌面和 Surface (PixelSense) 1.0 上运行的 WPF 应用程序的约定

标签 c# .net wpf cross-platform pixelsense

编辑:为避免混淆:这是关于以前称为或仍称为 Microsoft Surface 1.0 的表。不是以前叫微软Surface 2.0的 table ,也不是现在叫微软Surface的平板电脑。 编辑结束

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

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

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

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

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's documentation on the PixelSense presentation layer 等资源中的声明所证实的那样。 , SO 问题 such as this one related to a WPF tree view另请参阅,this blogpost on the PixelSense WPF layerthis SO question on how to rewrite a WPF desktop application for PixelSense .后一个页面甚至将所需的更改称为最小,但它们仍然是更改。

此外,对 this SO question on how to use a particular WPF desktop control on PixelSense 的 react 暗示使用 .NET 4.0 可能会简化事情,但我认为 PixelSense 不支持 .NET 4.0 1.0 SDK(据我所知,它是基于 .NET 3.5 的)。

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

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

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

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

    最佳答案

    让我们从回到 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 的 native 触摸堆栈,并将它们作为内置于 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)并且包括本质上是 Surface Toolkit for Windows 的更新版本,尽管现在控件已重新设计为地铁。最后,产品时间线已经同步,您可以使用单一代码库为两个平台构建出色的触控体验。

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

  • 使用 WPF 4 API 和 Surface Toolkit 构建您的应用程序
    视窗触控
  • 编写一些接受 Surface 输入事件的代码并
    通过 WPF 4 的输入堆栈路由它(执行此操作的能力不是
    非常广为人知,但它是专门为这种类型的
    设想)。

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

    关于c# - 在桌面和 Surface (PixelSense) 1.0 上运行的 WPF 应用程序的约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11257909/

    相关文章:

    c# - 带参数的 UserControl 构造函数

    c# - 如何将歌曲的持续时间格式化为分钟和秒?

    c# - 为什么我应该使用属性而不是实现接口(interface)?

    .net - 使用 .NET 或 MS SQL 模拟 MySql 的 password() 加密

    针对客户端配置文件的 .Net 4.0 应用程序仍然提示用户下载完整配置文件

    调用 web api 时 C# 不支持授权类型

    c# - 如何将 WPF CollectionViewGroup 类型更改为自定义类型并在 ListCollectionView 中使用它

    c# - 无法使用适用于 .NET 的 EMDK

    wpf - Autofac:将 LifeTimeScope 与 MVVM 中 ViewModel 的生命周期相关联

    wpf - WPF 中的 StatusBarItem 类有什么意义?