6

F# 不支持部分类也不支持 XAML 文件的预编译。解决方法:在运行时加载图形对象定义,而不是后面的编译时代码。有多种方法可以为 XamlReader 提供引用的资源文件的内容。

open System.Windows

// from Resource
let uri = System.Uri "pack://application:,,,/AssemblyName;component/MainWindow.xaml"
let info = Application.GetResourceStream uri
let wnd = Markup.XamlReader.Load info.Stream :?> Window

// from Embedded resource
let assembly = System.Reflection.Assembly.GetExecutingAssembly()
let stream = assembly.GetManifestResourceStream "MainWindow.xaml"
let wnd  = Markup.XamlReader.Load stream :?> Window

类型提供者应该能够将至少部分工作转移回编译时。

open FsXaml
type MainWindow = XAML<"MainWindow.xaml"> 
let mainwnd = new MainWindow()
let wnd = mainwnd.Root

类型安全(和发现)的收益似乎是微不足道的:每个资源的一种运行时类型转换更少。还有其他优点吗?

4

2 回答 2

8

类型安全(和发现)的收益似乎是微不足道的:每个资源的一种运行时类型转换更少。

即使在您显示的代码中,这里还有其他优点。在您的示例中使用 FsXaml 更加简洁,并且完全类型安全。如果 XAML 文件中存在重大问题,它也会在编译时失败,使用 XAML 加载程序会将其推迟到运行时。

还有其他优点吗?

有很多优点——

  • 更短的代码
  • 类型安全
  • 以类型安全的方式作为属性公开的命名元素
  • (最重要)创建与您的 XAML 类型相对应的实际类型

最后一点确实是 FsXaml 与 XamlReader 的“杀手”优势——没有这一点,除了 WPF 中的“玩具”项目之外,几乎不可能做任何事情。如果您希望能够嵌入 XAML,则需要具有与您的类型相对应的“真实类型”。

例如,如果您想使用作为数据模板开发的 UserControl,您需要将 UserControl 设为实际类型,而不仅仅是将某些 XAML 作为资源。使用 XamlReader,无法从其他 XAML 引用它。您也无法重用资源、将数据拉入您的应用程序或许多其他事情(无需在运行时手动编写大量管道)。

此外,使用 FsXaml 2+,您可以子类化类型并在“代码背后”中提供完整的逻辑,与您在 C# 中的工作方式类似(尽管不同)。

这使 Xaml 更接近于在 C# 中工作时的体验 - 仍然没有 BAML 编译(一个缺点),但除此之外,当使用 F# 和 WPF 工作时,您获得的体验实际上与 C# 相当。

于 2016-06-14T18:10:52.253 回答
1

类型提供程序在编译时检查,Xaml 阅读器在运行时工作。
因此,错误要么在编译时检测到,要么在运行时检测到。很明显,在开发过程中尽早发现错误会更好。

于 2015-06-16T05:51:22.847 回答