I have a WPF application (MVVM Toolkit) with a data model which was scaffolded using EFcore tools from a database. The resulting model for one specific class looks like this:
public partial class BomLine
{
public int Id { get; set; }
public int ProjectId { get; set; }
public string? Manufacturer { get; set; }
public string? ManufacturerPartNumber { get; set; }
public string? InternalPartNumberSelected { get; set; }
}
A list of such items ObservableCollection<BomLine>
are displayed in a ListView
. This works as expected. There is an additional binding on the value of InternalPartNumberSelected
which gives the respective line a distinct color.
Now, when the value of InternalPartNumberSelected
changes, no PropertyChanged event is fired (of course, there is no [ObservableProperty]
or other explicit RaisePropertyChanged command.
I could now change the Scaffolded data to
public partial class BomLine : ObservableObject
{
public int Id { get; set; }
public int ProjectId { get; set; }
public string? Manufacturer { get; set; }
public string? ManufacturerPartNumber { get; set; }
[ObservableProperty] string? _internalPartNumberSelected;
}
This would make the color change visible because now a Property Change event is fired and the Binding re-evalued.
Yet, this seems like a bad solution because it requires tinkering with scaffolded data (which would be overwritten).
Is there a "correct" approach to that problem? I'm using .net core 8 / efcore 8, WPF, MVVM toolkit.
You can keep separation of EF from view models by using an approach explained at https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/observableobject#wrapping-a-non-observable-model. In your case it would be something like this:
public class BomLineViewModel : ObservableObject
{
private readonly BomLine model;
public BomLineViewModel(BomLine model)
{
this.model = model;
}
public int Id
{
get => model.Id;
// no setter, Id is readonly
}
public int ProjectId
{
get => model.ProjectId;
set => SetProperty(model.ProjectId, value, model, (m, v) => m.ProjectId = v);
}
public string? Manufacturer
{
get => model.Manufacturer;
set => SetProperty(model.Manufacturer, value, model, (m, v) => m.Manufacturer = v);
}
public string? ManufacturerPartNumber
{
get => model.ManufacturerPartNumber;
set => SetProperty(model.ManufacturerPartNumber, value, model, (m, v) => m.ManufacturerPartNumber = v);
}
public string? InternalPartNumberSelected
{
get => model.InternalPartNumberSelected;
set => SetProperty(model.InternalPartNumberSelected, value, model, (m, v) => m.InternalPartNumberSelected = v);
}
}
That way you can add even other things to the view model and they won't affect EF.