Home > database >  How handle binding ObservableCollections when implementing MVVM Pattern in a blazor application?
How handle binding ObservableCollections when implementing MVVM Pattern in a blazor application?

Time:05-09

Since the page classes in my blazor application are getting somewhat long and untidy and I'm coming originally from WPF development anyway, I thought, I have a look into MVVM-ifying my application.

Preliminaries:

Here is my ViewModelBase

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void SetProperty<T>(ref T storage, T value,
        [CallerMemberName] string property = null)
    {
        if (object.Equals(storage, value)) return;
        storage = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }
}

And here is a relevant of the relevant ViewModel and the corresponding interface for the Dependency-Injection system:

public class DatasetManagerViewModel : ViewModelBase, IDatasetManagerViewModel
{
    private DatasetModel _selectedDataset;
    public DatasetModel SelectedDataset 
    { 
        get { return _selectedDataset;}
        set { SetProperty(ref _selectedDataset, value); }
    }

    public ObservableCollection<ImageModel> DatasetFiles { get; set; } = new();
}

public interface IDatasetManagerViewModel
{
    event PropertyChangedEventHandler PropertyChanged;
    ObservableCollection<ImageModel> DatasetFiles { get; set; }
    DatasetModel SelectedDataset { get; set; }
}

In the View/Page Class this is implemented as follows:

[Inject]
protected IDatasetManagerViewModel ViewModel { get; private set; }

private async void OnPropertyChangedHandler(object sender, PropertyChangedEventArgs e)
{
    await InvokeAsync(() =>
    {
        StateHasChanged();
    });
}

protected override async Task OnInitializedAsync()
{
    ViewModel.PropertyChanged  = OnPropertyChangedHandler;   
    await base.OnInitializedAsync();
}
// also unsubscribe event after disposal

Question:

This works fine in case of normal properties such as in case of the above SelectedDataset. However, I'm wondering what the best way is to bind an ObservableCollection such as DatasetFiles to the view class to incorporate the CollectionChanged event (If I recall correctly this is done automatically in WPF when a GUI element is bound to an ObservableCollection?).

CodePudding user response:

In the meanwhile I changed my ViewModelBase to the following:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void SetProperty<T>(ref T storage, T value,
        [CallerMemberName] string property = null)
    {
        if (object.Equals(storage, value)) return;
        storage = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }

    protected void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
    }
}

Any ViewModel with an ObservableCollection is then responsible to subscribe the added OnCollectionChanged() to the CollectionChanged event. If anyone comes up with a nicer solution, I'd be interessted :)

  • Related