So I've been doing quite a bit of digging and I haven't been able to find any real definitive answer to this anywhere.
I'm writing an application using MVVM Light and WPF. I have a service that is injected into my ViewModel that checks the validity of a certain property that is set. The service makes a web-call, and it is asynchronous. The call does not need to halt execution of the application, and it's solely to provide visual feedback to the user as to the validity of the entered value.
As such, I've managed to hack something together to get it to work, but it feels somewhat hackey.
What is the proper way to execute an asynchronous method on a property change without resorting to something like async void
?
Here's what I currently have.
public string OmmaLicenseNumber
{
get => _ommaLicenseNumber;
set
{
Set(() => OmmaLicenseNumber, ref _ommaLicenseNumber, value);
Patient.OmmaLicenseNumber = value;
var _ = CheckLicenseValid();
}
}
private async Task CheckLicenseValid()
{
var valid = await _licenseValidationService.IsValidAsync(OmmaLicenseNumber);
// We don't want the UI piece showing up prematurely. Need 2 properties for this;
LicenseValid = valid;
LicenseInvalid = !valid;
}
If I simply attempt to call .Result
on The async method, it results in a deadlock that requires an application restart to fix. And while what I have works, I'm not really a fan. What are my other options?
Event handlers allow for the use of async void
Reference Async/Await - Best Practices in Asynchronous Programming
public string OmmaLicenseNumber {
get => _ommaLicenseNumber;
set {
Set(() => OmmaLicenseNumber, ref _ommaLicenseNumber, value);
Patient.OmmaLicenseNumber = value;
//Assuming event already subscribed
//i.e. OmmaLicenseNumberChanged += OmmaLicenseNumberChanged;
OmmaLicenseNumberChanged(this,
new LicenseNumberEventArgs { LicenseNumber = value }); //Raise event
}
}
private event EventHandler<LicenseNumberEventArgs> OmmaLicenseNumberChanged = delegate { };
private async void OnOmmaLicenseNumberChanged(object sender, LicenseNumberEventArgs args) {
await CheckLicenseValid(args.LicenseNumber); //<-- await async method call
}
private async Task CheckLicenseValid(string licenseNumber) {
var valid = await _licenseValidationService.IsValidAsync(licenseNumber);
// We don't want the UI piece showing up prematurely. Need 2 properties for this;
LicenseValid = valid;
LicenseInvalid = !valid;
}
//...
public class LicenseNumberEventArgs : EventArgs {
public string LicenseNumber { get; set; }
}
Do I think this to be a little heavy handed?
Yes. This is just meant as an example to show that it is doable.
Can this be refactored to some simpler helper/utility method call?
Yes. Could look a lot like an awaitable callback pattern using expressions to get value to validate
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With