ITPub博客

首页 > 应用开发 > IT综合 > dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用

dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用

原创 IT综合 作者:uu365 时间:2021-05-23 16:14:05 0 删除 编辑

  本文来安利大家一个有趣而且强大的库,通过F#和C#混合编程编写WPF应用,可以在WPF中使用到F#强大的数据处理能力

  在阅读本文之前,我期望大家已了解部分F#的知识。在学会C#基础知识之下,了解F#基础知识是很快的,而本文也仅仅只是用到很少的知识。大家都知道,使用F#能带来很好的数据处理能力,从F#语法层面带来的编写效率提升和编写逻辑的优化,而F#本身是没有带GUI可视化应用编程的。但是F#是在dotnet体系下的,天然就可以用上dotnet系的技术,当然就包括WPF了。因此上一句话说F#本身是没有带GUI可视化应用编程是完全错误的,因为F#可以非常方便调起WPF和WinForms等成熟的UI框架作为自身的可视化应用框架

  通过Elmish.WPF库,将可以让开发更顺,以下是一个简单的例子。这个例子的代码完全放在Elmish.WPF库里。

  咱依然通过VS创建一个空白的C#空白WPF程序,在此例子里面,几乎没有C#多少的戏份,只是为了使用C#更好的驱动WPF程序而已,因为部分初始化方法和类型等在F#写起来的代码量可不少。本文的主角将交给XAML和F#这两个语言

  打开App.xaml.cs文件,咱将修改本文仅有的一点C#代码

  public partial class App:Application

  {

  public App()

  {

  this.Activated+=StartElmish;

  }

  private void StartElmish(object sender,EventArgs e)

  {

  this.Activated-=StartElmish;

  Program.main(MainWindow);

  }

  }

  以上代码的Program类是在F#项目里面编写的,也就是说C#语言只是胶水,用来做初始化的连接

  接下来咱来创建一个简单的界面,这个界面如下

  基本功能是点击加号和减号分别实现当前数值的加减

  大概的XAML代码如下

  <StackPanel Orientation="Horizontal"HorizontalAlignment="Center"VerticalAlignment="Top"Margin="0,25,0,0">

  <TextBlock Text="{Binding CounterValue,StringFormat='Counter value:{0}'}"Width="110"Margin="0,5,10,5"/>

  <Button Command="{Binding Decrement}"Content="-"Margin="0,5,10,5"Width="30"/>

  <Button Command="{Binding Increment}"Content="+"Margin="0,5,10,5"Width="30"/>

  <TextBlock Text="{Binding StepSize,StringFormat='Step size:{0}'}"Width="70"Margin="0,5,10,5"/>

  <Slider Value="{Binding StepSize}"TickFrequency="1"Maximum="10"Minimum="1"IsSnapToTickEnabled="True"Width="100"Margin="0,5,10,5"/>

  <Button Command="{Binding Reset}"Content="Reset"Margin="0,5,10,5"Width="50"/>

  </StackPanel>

  在XAML中定义了命令和值的绑定,没有做实际的实现

  接下来创建一个F#项目,将这个项目被刚才创建的WPF项目所引用,将WPF项目作为启动项目。运行的顺序是先启动WPF项目,进入App类里面,在App的Activated事件,调用F#项目的逻辑,然后接下来就交给F#来进行数据绑定,在F#项目中,将给MainWindow附加自身作为DataContext数据用于在XAML绑定

  在F#的Program.fs文件里面添加如下代码

  module Elmish.WPF.Samples.SingleCounter.Program

  open Serilog

  open Serilog.Extensions.Logging

  open Elmish.WPF

  type Model=

  {Count:int

  StepSize:int}

  type Msg=

  |Increment

  |Decrement

  |SetStepSize of int

  |Reset

  let init=

  {Count=0

  StepSize=1}

  let canReset=(<>)init

  let update msg m=

  match msg with

  |Increment->{m with Count=m.Count+m.StepSize}

  |Decrement->{m with Count=m.Count-m.StepSize}

  |SetStepSize x->{m with StepSize=x}

  |Reset->init

  let bindings():Binding<Model,Msg>list=[

  "CounterValue"|>Binding.oneWay(fun m->m.Count)

  "Increment"|>Binding.cmd Increment

  "Decrement"|>Binding.cmd Decrement

  "StepSize"|>Binding.twoWay(

  (fun m->float m.StepSize),

  int>>SetStepSize)

  "Reset"|>Binding.cmdIf(Reset,canReset)

  ]

  let designVm=ViewModel.designInstance init(bindings())

  let main window=

  let logger=

  LoggerConfiguration()

  .MinimumLevel.Override("Elmish.WPF.Update",Events.LogEventLevel.Verbose)

  .MinimumLevel.Override("Elmish.WPF.Bindings",Events.LogEventLevel.Verbose)

  .MinimumLevel.Override("Elmish.WPF.Performance",Events.LogEventLevel.Verbose)

  .WriteTo.Console()

  .CreateLogger()

  WpfProgram.mkSimple(fun()->init)update bindings

  |>WpfProgram.withLogger(new SerilogLoggerFactory(logger))

  |>WpfProgram.startElmishLoop window

  十分简单的逻辑,在F#定义的命令等将可以通过Elmish.WPF库和WPF的XAML绑定,相当于XAML提供界面逻辑,而F#提供数据驱动的处理逻辑。各个语言的职责是XAML负责界面,而F#负责后台逻辑。将XAML和F#连接起来以及应用程序的启动是C#语言。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69997029/viewspace-2773551/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2021-03-23

  • 博文量
    14
  • 访问量
    37637