使用WPF的F#事件驱动的MVVM

时间:2021-02-17 22:33:48

I've been working with Event driven MVVM for a couple of weeks (first time using a design pattern in F#) and I like the idea of separating view and model and also the "functional" controller. But when going through a book on WPF I get the feeling it would be easier if I could adress events directly. Also in some situations I need to get a hold on a control from code behind.

我一直在使用事件驱动的MVVM几周(第一次使用F#中的设计模式),我喜欢分离视图和模型以及“功能”控制器的想法。但是当我阅读一本关于WPF的书时,我觉得如果我可以直接处理事件会更容易。此外,在某些情况下,我需要从代码后面控制一个控件。

More specific:

更具体:

  • How to close a window defined as usercontrol in a XAML file
  • 如何关闭在XAML文件中定义为usercontrol的窗口
  • It seems there would be less need for buttons (triggering booleans that hold state), with a more automated feel as result, if I could directly adress events
  • 似乎对按钮的需求较少(触发保持状态的布尔值),如果我可以直接对事件进行处理,则会产生更自动化的感觉

Does anybody share this experience or am I still missing something? Is it advisable to go back to FsXaml or polyglot MVVM?

有没有人分享这种经历,还是我还缺少什么?是否可以回到FsXaml或多语言MVVM?

1 个解决方案

#1


4  

Turns out the code is actually very easy to extend. Based on demos I was able to turn a textbox into a numeric one. The code that does this is very basic, but my intent was to define a custom event accessor. Which can be done by:

原来代码实际上很容易扩展。基于演示,我能够将文本框转换为数字文本框。执行此操作的代码非常基本,但我的目的是定义自定义事件访问器。可以通过以下方式完成:

Extend UserControl.xaml header with:

使用以下内容扩展UserControl.xaml标头:

xmlns:fsxaml="http://github.com/fsprojects/FsXaml"   
fsxaml:ViewController.Custom="{x:Type views:CompositionUserControl}"

And replace the original code in UserControl.xaml.fs:

并替换UserControl.xaml.fs中的原始代码:

namespace Space.Views

open FsXaml

type UserView = XAML<"View/UserControl.xaml", true>

type CompositionUserControl () =

    member __.ViewModel = Space.ViewModels.UserControlViewModel(Space.Models.Handling.proces)

with

namespace Space.Views

open FsXaml
open System

type UserView = XAML<"View/UserControl.xaml", true>

type CompositionUserControl () =
    inherit UserControlViewController<UserView>()

    let numeric (txt : string) =
        try txt |> int with
        | :? System.FormatException -> 0
        | _ -> 1

    override this.OnLoaded view = 
        view.Box.PreviewTextInput.Add(fun e -> if numeric e.Text = 0 then e.Handled <- true) 

    member __.ViewModel = Space.ViewModels.UserControlViewModel(Space.Models.Handling.proces)

EDIT

编辑

Looking back at this post, here's my progress regarding my initial questions:

回顾这篇文章,这是我在初步问题上取得的进展:

How to close a window defined as usercontrol in a XAML file

如何关闭在XAML文件中定义为usercontrol的窗口

Using an attached property DialogCloser.

使用附加属性DialogCloser。

It seems there would be less need for buttons (triggering booleans that hold state), with a more automated feel as result, if I could directly adress events

似乎对按钮的需求较少(触发保持状态的布尔值),如果我可以直接对事件进行处理,则会产生更自动化的感觉

The key here is to learn:

这里的关键是学习:

  1. How to truly separate View(Model) from Model
  2. 如何真正地将View(Model)与Model分开
  3. How to use XAML to exploit its full power
  4. 如何使用XAML充分利用其全部功能

#1


4  

Turns out the code is actually very easy to extend. Based on demos I was able to turn a textbox into a numeric one. The code that does this is very basic, but my intent was to define a custom event accessor. Which can be done by:

原来代码实际上很容易扩展。基于演示,我能够将文本框转换为数字文本框。执行此操作的代码非常基本,但我的目的是定义自定义事件访问器。可以通过以下方式完成:

Extend UserControl.xaml header with:

使用以下内容扩展UserControl.xaml标头:

xmlns:fsxaml="http://github.com/fsprojects/FsXaml"   
fsxaml:ViewController.Custom="{x:Type views:CompositionUserControl}"

And replace the original code in UserControl.xaml.fs:

并替换UserControl.xaml.fs中的原始代码:

namespace Space.Views

open FsXaml

type UserView = XAML<"View/UserControl.xaml", true>

type CompositionUserControl () =

    member __.ViewModel = Space.ViewModels.UserControlViewModel(Space.Models.Handling.proces)

with

namespace Space.Views

open FsXaml
open System

type UserView = XAML<"View/UserControl.xaml", true>

type CompositionUserControl () =
    inherit UserControlViewController<UserView>()

    let numeric (txt : string) =
        try txt |> int with
        | :? System.FormatException -> 0
        | _ -> 1

    override this.OnLoaded view = 
        view.Box.PreviewTextInput.Add(fun e -> if numeric e.Text = 0 then e.Handled <- true) 

    member __.ViewModel = Space.ViewModels.UserControlViewModel(Space.Models.Handling.proces)

EDIT

编辑

Looking back at this post, here's my progress regarding my initial questions:

回顾这篇文章,这是我在初步问题上取得的进展:

How to close a window defined as usercontrol in a XAML file

如何关闭在XAML文件中定义为usercontrol的窗口

Using an attached property DialogCloser.

使用附加属性DialogCloser。

It seems there would be less need for buttons (triggering booleans that hold state), with a more automated feel as result, if I could directly adress events

似乎对按钮的需求较少(触发保持状态的布尔值),如果我可以直接对事件进行处理,则会产生更自动化的感觉

The key here is to learn:

这里的关键是学习:

  1. How to truly separate View(Model) from Model
  2. 如何真正地将View(Model)与Model分开
  3. How to use XAML to exploit its full power
  4. 如何使用XAML充分利用其全部功能