In my previous question "Enabling dialog OK button with FSharp.ViewModule", I got to the point where a dialog's OK button was enabled only when the validators for the dialog's fields were true, and ViewModule's IsValid property became true. But I ran into a couple more problems after that:
1) Clicking on the OK button didn't close the dialog, even if I set IsDefault="true"
in XAML.
2) When the OK button is clicked, sometimes I want to do more checks than provided by the ViewModule validators (eg, checking an email address). Then I want to stop the dialog from closing if this custom validation fails.
But I don't know how to do both when using F# and MVVM. First I tried putting the XAML into a C# project and the view model code in an F# library. And then I used the OK button's Click handler in code behind to close the window. This fixed 1), but not 2).
So this is my 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"--> />
And my view model - with a comment in the validate
function to show what I want to do when the OK button is clicked:
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
)