gpt4 book ai didi

wpf - 使用 FSharp.ViewModule 关闭对话框

转载 作者:行者123 更新时间:2023-12-02 06:02:59 25 4
gpt4 key购买 nike

在我之前的问题“使用 FSharp.ViewModule 启用对话框“确定”按钮”中,我发现只有当对话框字段的验证器为 true 并且 ViewModule 的 IsValid 属性为 true 时,才启用对话框的“确定”按钮。但之后我遇到了更多问题:

1) 即使我在 XAML 中设置了 IsDefault="true",单击“确定”按钮也没有关闭对话框。

2) 当单击“确定”按钮时,有时我想要执行比 ViewModule 验证器提供的更多检查(例如,检查电子邮件地址)。然后,如果此自定义验证失败,我想阻止对话框关闭。

但我不知道如何在使用 F# 和 MVVM 时同时执行这两种操作。首先,我尝试将 XAML 放入 C# 项目中,并将 View 模型代码放入 F# 库中。然后我在后面的代码中使用“确定”按钮的“单击”处理程序来关闭窗口。这修复了 1),但未修复 2)。

这是我的 XAML:

<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="OK" IsEnabled="{Binding IsValid}" IsDefault="true" Command="{Binding OkCommand}"
<!--Click="OnOK"--> />

我的 View 模型 - 在 validate 函数中添加注释,以显示单击“确定”按钮时我想要执行的操作:

let name = self.Factory.Backing( <@ self.Name @>, "", notNullOrWhitespace)
let email = self.Factory.Backing( <@ self.Email @>, "", notNullOrWhitespace)
let dialogResult = self.Factory.Backing( <@ self.DialogResult @>, false )

let isValidEmail (e:string) = e.Length >= 5

member self.Name
with get() = name.Value
and set value = name.Value <- value
member self.Email
with get() = email.Value
and set value = email.Value <- value
member self.DialogResult
with get() = dialogResult.Value
and set value = dialogResult.Value <- value

member self.OkCommand = self.Factory.CommandSync(fun () ->
if not <| isValidEmail(email.Value) then
MessageBox.Show("Invalid Email") |> ignore
else
dialogResult.Value <- true
)

最佳答案

值得指出的是,MVVM 和代码隐藏并不是最好的 friend 。

您引用的 C# 事件处理程序位于 Window的代码隐藏文件(即部分类)。尽管代码隐藏对于 View 相关逻辑来说被认为是可以的,但 MVVM 纯粹主义者却对此不以为然。因此,MVVM 更喜欢使用 Commands,而不是在 XAML 中指定事件处理程序。 .

选项 A - 在代码隐藏中执行,务实。

请注意,FsXaml 不提供事件的直接连接(在 XAML 中指定处理程序),但您可以在代码隐藏中自行连接事件。

在 XAML 中命名控件后,您可以在相应的源文件中保留它。

UserDialog.xaml

<Button x:Name="butt" ... >

UserDialog.xaml.fs

namespace Views

open FsXaml

type UserDialogBase = XAML<"UserDialog.xaml">

type UserDialog() as dlg =
inherit UserDialogBase()

do dlg.butt.Click.Add( fun _ -> dlg.DialogResult <- System.Nullable(true) )

验证最好在 ViewModel 中处理,例如对电子邮件地址使用自定义验证:

选项 B - 您可以使用 DialogCloser 遵循 MVVM 模式.

首先在解决方案顶部添加一个新的源文件(解决方案资源管理器)

DialogCloser.fs

namespace Views

open System.Windows

type DialogCloser() =
static let dialogResultProperty =
DependencyProperty.RegisterAttached("DialogResult",
typeof<bool>, typeof<DialogCloser>,
new PropertyMetadata(DialogCloser.DialogResultChanged))

static member SetDialogResult (a:DependencyObject) (value:string) =
a.SetValue(dialogResultProperty, value)

static member DialogResultChanged
(a:DependencyObject) (e:DependencyPropertyChangedEventArgs) =
match a with
| :? Window as window
-> window.DialogResult <- System.Nullable (e.NewValue :?> bool)
| _ -> failwith "Not a Window"

假设我们的解决方案名为 WpfApp (在 XAML header 中引用),然后我们可以实现 DialogCloser像这样:

UserDialog.xaml

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:Views;assembly=WpfApp"
xmlns:fsxaml="http://github.com/fsprojects/FsXaml"
views:DialogCloser.DialogResult="{Binding DialogResult}"
>

...

</Window>

现在在UserDialog的 ViewModel 你可以连接一个 Command并通过设置 dialogResult 关闭对话框为真。

member __.OkCommand = __.Factory.CommandSync(fun () ->
if not <| isValidEmail(email.Value) then
System.Windows.MessageBox.Show ("...") |> ignore
else
// do stuff (e.g. saving data)

...

// Terminator
dialogResult.Value <- true
)

您还可以跳过 if/else 子句并使用自定义验证来验证电子邮件。

为了结束它,您可以使用此辅助函数从 MainViewModel 调用对话框:

UserDialog.xaml.fs

namespace Views

open FsXaml

type UserDialog = XAML<"UserDialog.xaml">

module UserDialogHandling =
/// Show dialog and return result
let getResult() =
let win = UserDialog()
match win.ShowDialog() with
| nullable when nullable.HasValue
-> nullable.Value
| _ -> false

请注意,在这种情况下没有“代码隐藏”(UserDialog 类型声明中没有代码)。

关于wpf - 使用 FSharp.ViewModule 关闭对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40991100/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com