So I recently started working with MVVM, finally starting to get the concept down.
I seem to have stumbled on to a minor issue with commands.
I created a project that had a button and a textbox and the plan was to click the button and then generate some text to the textbox.
Using MVVM ofcourse.
So I managed to get it to work, the only issue is that with my button being bound to a command and what not, when clicking the button my UI froze, there are obvious reasons to why this is, but that got me thinking. To prevent UI deadlocks you would usually use async & await but with this, it started nagging about the method not being awaited in Execute(); in the Command that is.
What is the proper way to deal with UI deadlocks like the one in this scenario?
Would I make a AsyncCommand or.. ?
Also if I need an AsyncCommand what's the propper way of creating one?
View
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<Button Height="50"
Width="150"
Content="Add Product"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Command="{Binding AddProductCommand}"/>
<TextBox Width="200"
Margin="0,10,0,0"
Text="{Binding MyProduct.ProductName}"/>
</StackPanel>
Model
public class ProductModel : INotifyPropertyChanged
{
private string _productName;
private double _productPrice;
public double ProductPrice
{
get { return _productPrice; }
set
{
_productPrice = value;
OnPropertyChanged("ProductPrice");
}
}
public string ProductName
{
get { return _productName; }
set
{
_productName = value;
OnPropertyChanged("ProductName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
ViewModel
public class ViewModel : INotifyPropertyChanged
{
private ProductService _productService;
private ProductModel _myProduct;
public AddProductCommand AddProductCommand { get; set; }
public ViewModel()
{
_productService = new ProductService();
_myProduct = new ProductModel();
AddProductCommand = new AddProductCommand(this);
}
//Bind a button to a command that invokes this method.
public void FillDescription()
{
_myProduct.ProductName = _productService.GetProductName();
}
public ProductModel MyProduct
{
get { return _myProduct; }
set
{
_myProduct = value;
OnPropertyChanged("MyProduct");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Service
public class ProductService
{
public ProductService()
{
}
public string GetProductName()
{
var web = new HtmlWeb();
var doc = web.Load("https://shop.supersimpleonline.com/products/baby-shark-official-plush");
var title = doc.DocumentNode.SelectNodes("//h1[@itemprop = 'name']").FirstOrDefault(x => x != null).InnerText;
return title;
}
}
Command
public class AddProductCommand : ICommand
{
public ViewModel ViewModel { get; set; }
public AddProductCommand(ViewModel viewModel)
{
ViewModel = viewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
ViewModel.FillDescription();
}
public event EventHandler CanExecuteChanged;
}