F# doesn't support partial classes nor precompilation of XAML files. The workaround: instead of compile-time code behind, load graphical object definitions at runtime. There are various ways to supply XamlReader with the content of a referenced resource file.
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
Type providers should be able to shift at least part of that effort back to compile-time.
open FsXaml
type MainWindow = XAML<"MainWindow.xaml">
let mainwnd = new MainWindow()
let wnd = mainwnd.Root
The gain in type safety (and discovery) seems to be marginal: one runtime type cast less per resource. Are there other advantages?
The gain in type safety (and discovery) seems to be marginal: one runtime type cast less per resource.
There are other advantages here, even in the code you displayed. Using FsXaml is far more concise in your example, and fully type safe. It will also fail at compile time if there are major issues in your XAML files, where using XAML Loader defers this to runtime.
Are there other advantages?
There are many advantages -
The last point is really the "killer" advantage of FsXaml vs XamlReader - without this, it's nearly impossible to do anything beyond "toy" projects in WPF. You need to have "real types" corresponding to your types if you want to be able to embed XAML.
For example, if you want to use UserControls you develop as data templates, you need that UserControl to be an actual type, not just some XAML as a resource. Using XamlReader, there's no way to reference that from other XAML. You also can't reuse resources, pull data into your Application, or many other things (without resorting to hand-writing a huge amount of plumbing to do it at runtime).
In addition, with FsXaml 2+, you can subclass types and provide full logic within the "code behind", similarly (though differently) from how you work in C#.
This brings Xaml much, much closer to the experience when working in C# - There is still no BAML compilation (the one disadvantage), but otherwise, you get an experience that is effectively on-par with C# when working from F# with WPF.
A type provider checks things at compile time, the Xaml reader works at run time.
Thus errors are either detected at compile or at run time. It is pretty obvious that finding errors earlier in the development process is better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With