Как включить проект WinForms или WPF в F #?

У меня установлена самая последняя версия Visual Studio 2017. Я выбрал поддержку языка F # и поддержку рабочего стола F #. После перезагрузки и перехода в Файл → Новый проект я ожидал увидеть возможность запуска нового проекта WPF или WinForms для F #, но у меня нет таких параметров. Только консоль, библиотека, ядро ASP.NET и учебник.

Как включить или найти новые шаблоны проектов для настольных приложений F #?

Ответ 1

Насколько я знаю, шаблонов WPF или WinForms на F # нет, но (по крайней мере, в VS2015) есть набор шаблонов сообщества для приложений WPF. Честно говоря, вам не нужен шаблон, особенно если вы используете проект FSXaml, который делает это довольно легко сделать вручную (https://github.com/fsprojects/FsXaml).

Ответ 2

Вы можете создавать приложения WPF и WinForms в F #. Для этого нет шаблона, но это, безусловно, возможно, и многие люди это делают. Чтобы создать простое приложение WinForms, вы можете сделать следующее:

  • Создайте новое консольное приложение. Перейдите к свойствам проекта и измените "Тип вывода" на странице "Приложение" с "Консольное приложение" на "Приложение Windows",

  • Щелкните правой кнопкой мыши на "Ссылки" в проекте и добавьте ссылку на "System.Windows.Forms" и "System.Drawing" (на вкладке "Framework").

  • Замените код в Program.fs следующим Program.fs:

    open System.Windows.Forms
    
    let f = new Form()
    f.Controls.Add(new Label(Text="Hello world!"))
    Application.Run(f)
    

Для чего-то большего вы, вероятно, захотите использовать красивую библиотеку F # GUI, такую как проект FsXaml, упомянутый Isaac или Gjallarhorn, но основные первые шаги будут одинаковыми - создайте консольный проект, сделайте его проектом Windows, а затем добавьте соответствующие ссылки на графические интерфейсы.

Ответ 3

Это непростой ответ. Для этих проектов нет встроенного шаблона проекта, потому что ни Windows Forms, ни дизайнер WPF не понимают F #. Мы просто получили шаблоны ASP.NET Core для F #, поэтому нам не следует жаловаться... много.

С другой стороны, Winforms или WPF-приложение - это всего лишь код С#. Все, что вы делаете в дизайнере, заканчивается кодом в файле формы. Приложения Winforms или WPF являются "просто" консольными приложениями, которые настраивают надлежащую среду и создают формы и элементы управления.

Это на самом деле проще с использованием XAML и WP, особенно если вы используете MVVM или аналогичную архитектуру. Это потому, что вы можете развить разметку XAML отдельно от кода F # и привязать свои данные к XAML. Вы даже можете создать проект библиотеки классов WPF, создать Windows, страницы и элементы управления там без какого-либо кода, а затем использовать их в своем проекте F #.

Есть несколько библиотек, которые делают это проще. Один из вариантов - Elmish.WPF. Вы можете создавать страницы XAML и окна в отдельном проекте, а затем создавать модели и т.д. В F #, связывать их и запускать основную форму. Если вы проверите пример репо, большинство кода определяет записи и команды как функции F #, например:

type ClockMsg =
    | Tick of DateTime

type ClockModel =
    { Time: DateTime }

type Msg =
    | ClockMsg of ClockMsg
    | Increment
    | Decrement
    | SetStepSize of int

type Model = 
    { Count: int
      StepSize: int
      Clock: ClockModel }

а также

let init() = { Count = 0; StepSize = 1; Clock = { Time = DateTime.Now }}

let clockUpdate (msg:ClockMsg) (model:ClockModel) =
    match msg with
    | Tick t -> { model with Time = t }

let update (msg:Msg) (model:Model) =
    match msg with
    | Increment -> { model with Count = model.Count + model.StepSize }
    | Decrement -> { model with Count = model.Count - model.StepSize }
    | SetStepSize n -> { model with StepSize = n }
    | ClockMsg m -> { model with Clock = clockUpdate m model.Clock }

Их связывание относительно просто:

let view _ _ = 
    let clockViewBinding : ViewBindings<ClockModel,ClockMsg> =
        [ "Time" |> Binding.oneWay (fun m -> m.Time) ]

    [ "Increment" |> Binding.cmd (fun m -> Increment)
      "Decrement" |> Binding.cmdIf (fun m -> Decrement) (fun m -> m.StepSize = 1)
      "Count" |> Binding.oneWay (fun m -> m.Count)
      "StepSize" |> Binding.twoWay (fun m -> (double m.StepSize)) (fun v m -> v |> int |> SetStepSize)
      "Clock" |> Binding.vm (fun m -> m.Clock) clockViewBinding ClockMsg ]

И запуск всего приложения

[<EntryPoint;STAThread>]
 let main argv = 
     Program.mkSimple init update view
     |> Program.withSubscription subscribe
     |> Program.runWindow (Elmish.CounterViews.MainWindow())

Приведенный выше код исходит из образца счетчика. Представления XAML определены в проекте CounterViews. Вы даже можете удалить файлы .cs и проект будет полностью скомпилирован.