Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows UI (UWP or 8.1) in F# interactive

By referencing the default WPF DLLs, it's pretty easy to do anything you could do using code-only WPF:

#r "PresentationCore.dll"
#r "PresentationFramework.dll"
// ...other DLLs...
#r "WindowsBase.dll"

let window = System.Windows.Window()
let panel = System.Windows.Controls.StackPanel()
let button = System.Windows.Controls.Button()
panel.Children.Add button
button.Content <- "hi"

window.Content <- panel

window.Show()

... and you can manipulate it while the window is still open...

button.Click.Add (fun _ ->
    button.Content <-
        button.Content :?> string |> fun x -> (x + "!") :> obj)

...and then click the button to see it work. It seems like a pretty powerful way to build up UI components.

Is there any way to do the same thing with the Windows.UI namespace/controls/UI framework -- load some assemblies in F# interactive and instantiate UI components on the fly?

I've naively tried referencing the files that seemed relevant:

#r @"C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\2.0.0.0\Windows.Foundation.UniversalApiContract.winmd"
#r @"C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\2.0.0.0\Windows.Foundation.FoundationContract.winmd"

...and doing that gets me intellisense into the Windows.UI namespaces. But when I try to instantiate something:

Windows.UI.Xaml.Application()

I get:

error FS0193: Could not load file or assembly 'file:///C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\2.0.0.0\Windows.Foundation.UniversalApiContract.winmd' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)

like image 599
Overlord Zurg Avatar asked Jul 13 '16 05:07

Overlord Zurg


People also ask

What are the features of a UWP app?

Features of a UWP app. A UWP app is: Secure: UWP apps declare which device resources and data they access. The user must authorize that access. Able to use a common API on all devices that run Windows 10. Able to use device specific capabilities and adapt the UI to different device screen sizes, resolutions, and DPI.

What is UWP in Windows 10?

A common API surface across all devices Windows 10 introduces the Universal Windows Platform (UWP), which provides a common app platform on every device that runs Windows 10. The UWP core APIs are the same on all Windows devices.

How does uiui work with UWP?

UI elements respond to the size and DPI of the screen the app is running on by adjusting their layout and scale. UWP apps work well with multiple types of input such as keyboard, mouse, touch, pen, and Xbox One controllers.

How do I get Started with UWP?

UWP apps use WinRT APIs to provide powerful UI and advanced asynchronous features that are ideal for internet-connected devices. To download the tools you need to start creating UWP apps, see Get set up, and then write your first app. Where does UWP fit in the Microsoft development story?


2 Answers

There is no compiler support for WinRT assemblies, so you're not going to be able to reference an assembly as you're attempting to do and use the types in them cleanly.

On the other hand... since the .NET runtime has native support for WinRT types, you can use reflection to load those types and access their members. With a lot of effort, you could even build a type provider to provide a clean façade over that reflection and make it appear as though you can use the types directly. Here's a small example of how to directly call a WinRT API from F# via reflection:

open System.Reflection

let (?) (o:obj) s : 'a =
    let rec build ty args =
        if Reflection.FSharpType.IsFunction ty then
            let dom, rng = Reflection.FSharpType.GetFunctionElements ty
            let mkArgs =
                if dom = typeof<unit> then
                    if Reflection.FSharpType.IsFunction rng then failwith "Unit as non-final argument in curried definition?"
                    fun _ -> args
                else
                    fun arg -> arg::args
            Reflection.FSharpValue.MakeFunction(ty, fun o -> build rng (mkArgs o))
        else
            let rcvr,ty,flags =
                match o with
                | :? System.Type as ty -> null,ty,BindingFlags.Static
                | _ -> o,o.GetType(),BindingFlags.Instance
            let flags = flags ||| BindingFlags.Public
            let meth =
                if Reflection.FSharpType.IsFunction typeof<'a> then
                    query {
                        for m in ty.GetMethods(flags) do
                        where (m.Name = s)
                        where (m.GetParameters().Length = args.Length)
                        exactlyOne
                    }                    
                else
                    ty.GetProperty(s, flags).GetGetMethod()
            meth.Invoke(rcvr, args |> List.toArray)

    build typeof<'a> [] :?> 'a

let Clipboard = System.Type.GetType(@"Windows.ApplicationModel.DataTransfer.Clipboard, Windows.ApplicationModel, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime")

Clipboard?GetContent()?AvailableFormats |> Seq.iter (printfn "%s")
like image 108
kvb Avatar answered Oct 04 '22 12:10

kvb


My understanding is that there is no F# support for UWP yet.
See for instance this fresh open issue.

like image 33
weismat Avatar answered Oct 04 '22 11:10

weismat