FsXaml类型提供程序优于XamlReader

kae*_*fer 6 xaml f# fsxaml

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
Run Code Online (Sandbox Code Playgroud)

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

open FsXaml
type MainWindow = XAML<"MainWindow.xaml"> 
let mainwnd = new MainWindow()
let wnd = mainwnd.Root
Run Code Online (Sandbox Code Playgroud)

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

Ree*_*sey 8

类型安全(和发现)的增益似乎是微不足道的:每个资源的一个运行时类型减少.

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

还有其他优点吗?

有很多优点 -

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

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

例如,如果要使用作为数据模板开发的UserControl,则需要将UserControl设置为实际类型,而不仅仅是将某个XAML作为资源.使用XamlReader,无法从其他XAML引用它.您也无法重用资源,将数据提取到您的应用程序或许多其他事物(不需要手工编写大量的管道来在运行时执行此操作).

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

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