我可以在 Xamarin Forms 中使用 F# 创建 StackLayout 吗?

Can I create a StackLayout with F# in Xamarin Forms?

在他的 Xamarin 3 F# Awesomeness blog posting, Dave Thomas 中显示了正在创建的 StackLayout:

StackLayout.Create(
            [ 
              Entry (Placeholder = "Username") 
              Entry (Placeholder = "Password", IsPassword = true) 
              Button (Text = "Login", TextColor = Color.White, BackgroundColor = Color.FromHex "77D065") 
            ],...

但是,我得到一个错误未定义字段、构造函数或成员'Create'

如果我去掉括号前的.Create,错误信息会变成The member of object constructor 'StackLayout' takes 0 arguments but is here given 1.

我的解释是 Create 是一个采用元组的静态方法,但我在程序集浏览器的任何地方都看不到它的定义。 我也对他的示例感到有点困扰,因为在 TabbedPage 上使用了小写字母 create,所以看起来代码不一致并且可能在没有编译的情况下输入,尽管他在下面显示了屏幕截图。

我会采纳有关如何执行此操作的任何建议 - 如果没有缺少添加 Create 的神奇扩展,我很乐意采用其他方法。

父 class 声明 in the docs 是:

[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout,   IViewContainer<T>
where T : Xamarin.Forms.View

我想有一个习惯用法可以设置该内容 Children 属性 可作为 C# 的初始化使用,但可能不适用于 F#?

例如,我从 Forms Gallery sample 中得到编译代码,例如:

        StackLayout stackLayout = new StackLayout
        {
            Spacing = 0,
            VerticalOptions = LayoutOptions.FillAndExpand,
            Children = 
            {
                new Label
                {
                    Text = "StackLayout",
                    HorizontalOptions = LayoutOptions.Start
                },

我尝试将其转录为 F# 语法 - 以下是合法语法,但设置了子项 属性 时出现错误 对象构造函数 'StackLayout' 的成员没有参数或可设置 return 属性 'Children'。所需的签名是 StackLayout(): unit。 (FS0495)

  type App() = 
   static member GetMainPage =
    let sl = new StackLayout (
                  Spacing = 20,
                  VerticalOptions = LayoutOptions.FillAndExpand,
                  Children = [
                    new Label (Text = "StackLayout");
                    new Label (Text = "SuckLayout")
                  ]       
   )
   new ContentPage( Content = sl )

所以,让我感到困惑 - 我不知道为什么可以从 C# 而不是 F# 访问 Children。唯一有意义的怀疑是 XAML 内容 属性 注释以某种方式对一个编译器产生了影响,而对另一个编译器没有影响。

我是一位非常有经验的 C++ 和 Python 程序员,正在学习 F#(和 Swift),所以我可能会在语法上犯错误。我得到了元组,我开始习惯逗号的奇怪作用,幸运的是我的 Python 背景让我对空白感到放松。

其他人在博客 post 的评论中提出了同样的问题,但 post 没有回答。

我正在使用 Xamarin.iOS 8.10.0.258 Xamarin.Forms1.4.0.6341

我的退路是放弃 F# 的 GUI 并使用 C# 和 F# 的主要逻辑,但我真的很喜欢更紧凑的语法。


请注意,我也在他们的 forums

上问过这个问题

您显示的 C# 代码使用 C# 的集合初始化器功能,它将编译为对 Children.Add() 的调用,它没有设置 Children 属性.

F# 没有相同的集合初始化程序功能,因此您必须手动调用 Children.Add(),这很可能是 StackLayout.Create 函数正在做的事情。

StackLayout.Create 函数可能是在名为 StackLayout 的模块中定义的局部函数,这可以解释为什么您在文档中看不到它。

感谢上面的 Leaf Garland,这是固定函数 - 我只需要提示 C# 正在使用 Add

type App() =  
 static member GetMainPage =
  let sl = new StackLayout (
            Spacing = 20.0,
            VerticalOptions = LayoutOptions.FillAndExpand
    )
  let slc : View[] = [|
    new Entry (Placeholder = "Username") 
    new Entry (Placeholder = "Password", IsPassword = true) 
    new Button (Text = "Login", TextColor = Color.White, BackgroundColor = Color.FromHex "77D065") 
  |]
  slc |> Seq.iter (fun vc -> sl.Children.Add(vc))
  new ContentPage( Content = sl )

请注意,我必须创建临时变量 slc 以获得类型为超类 View

的数组

如果你有所有相同的类型,你可以使用文字列表和稍微简单的代码,如下所示:

type App() =  
 static member GetMainPage =
  let sl = new StackLayout (
            Spacing = 20.0,
            VerticalOptions = LayoutOptions.FillAndExpand
    )
  [
    new Label (Text = "StackLayout")
    new Label (Text = "SuckLayout")
  ] |> Seq.iter (fun vc -> sl.Children.Add(vc))
  new ContentPage( Content = sl )

Here's a nice article 关于 C# 集合初始化器,如果您感兴趣的话。

我今晚太忙了,但会尝试编写 StackLayout.Create 函数作为练习。