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

时间:2015-04-22 05:15:33

标签: f# xamarin xamarin.forms

在他的Xamarin 3 F# Awesomeness博文中,Dave Thomas显示正在创建StackLayout:

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

然而,我收到错误字段,构造函数或成员'创建'未定义

如果我在parens之前取出.Create,则错误消息将更改为对象构造函数的成员' StackLayout'取0个参数,但在这里给出1.

我的解释是Create是一个采用元组的静态方法,但我无法在程序集浏览器中的任何位置看到它。 我在他的示例中也被TabbedPage上使用的小写create打乱了,因此看起来代码不一致并且可能在没有编译的情况下输入,尽管他在下面显示了屏幕截图。

我会就如何做到这一点采取任何建议 - 如果没有遗漏添加创作的神奇扩展,我很乐意采取其他方法。

父类声明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#语法 - 以下是合法语法,但设置了Children属性会得到错误对象构造函数的成员&#39; StackLayout&#39;没有参数或可设置的退货财产&#39;儿童&#39;。所需的签名是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#访问。唯一有意义的是,不知何故,XAML内容属性注释会对一个编译器产生影响而不会对另一个编译器产生影响。

我是一位非常有经验的C ++和Python程序员,学习F#(和Swift),所以我很可能会绊倒语法。我得到了元组,我已经习惯了逗号的奇怪角色,幸好我的Python背景使我对空白感到放松。

其他人在博客文章的评论中也有同样的问题,但没有回复。

我正在使用Xamarin.iOS 8.10.0.258 Xamarin.Forms 1.4.0.6341

我的后备是放弃F#for GUI并使用C#那里用F#作为主逻辑但我真的很喜欢更紧凑的语法。


请注意,我也在forums

上提出了这个问题

2 个答案:

答案 0 :(得分:3)

您显示的C#代码正在使用C#的集合初始化程序功能,它将编译为Children.Add()的调用,而不是设置Children属性。

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

StackLayout.Create函数可以是在名为StackLayout的模块中定义的本地函数,它可以解释您在文档中没有看到它的原因。

答案 1 :(得分:0)

感谢上面的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函数编写为练习。