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 :)