You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I’m using the MVVM Community Toolkit to keep a ViewModel synchronized with a Model, handling both properties and collections. The [ObservableProperty] attribute already simplifies INotifyPropertyChanged implementation, but bidirectional synchronization between the ViewModel and Model still requires manually writing event handlers and update logic. This becomes repetitive and prone to errors, especially with multiple properties or collections.
Current Code:
Here’s my current ViewModel implementation, which synchronizes a Name property and an Items collection with a Model:
usingCommunityToolkit.Mvvm.ComponentModel;usingSystem.Collections.ObjectModel;usingSystem.Collections.Specialized;publicpartialclassViewModel:ObservableObject{privatereadonlyModelmodel;privateboolisSyncing=false;[ObservableProperty]privatestringname;[ObservableProperty]privateObservableCollection<string>items=newObservableCollection<string>();publicViewModel(Modelmodel){this.model=model;// Initialize properties from the ModelName=model.Name;// Initialize the collection from the Modelforeach(variteminmodel.Items){Items.Add(item);}// Sync properties: Update ViewModel when Model changesmodel.PropertyChanged+=(sender,e)=>{if(e.PropertyName==nameof(Model.Name)){Name=model.Name;}};// Sync collections: Update ViewModel.Items when Model.Items changesmodel.Items.CollectionChanged+=(sender,e)=>{if(!isSyncing){isSyncing=true;if(e.Action==NotifyCollectionChangedAction.Add){foreach(stringitemine.NewItems){Items.Add(item);}}elseif(e.Action==NotifyCollectionChangedAction.Remove){foreach(stringitemine.OldItems){Items.Remove(item);}}isSyncing=false;}};// Sync collections: Update Model.Items when ViewModel.Items changesItems.CollectionChanged+=(sender,e)=>{if(!isSyncing){isSyncing=true;if(e.Action==NotifyCollectionChangedAction.Add){foreach(stringitemine.NewItems){model.Items.Add(item);}}elseif(e.Action==NotifyCollectionChangedAction.Remove){foreach(stringitemine.OldItems){model.Items.Remove(item);}}isSyncing=false;}};}// Sync properties: Update Model when ViewModel's Name changespartialvoidOnNameChanged(stringvalue){model.Name=value;}}
Issue:
While functional, this code involves a lot of boilerplate:
Manual event subscriptions for PropertyChanged and CollectionChanged.
Explicit initialization of properties and collections from the Model.
Repeated logic to update one side when the other changes, including an isSyncing flag to avoid infinite loops.
Question:
Could the MVVM Community Toolkit leverage source generators to eliminate this boilerplate? I’d love to see a solution where synchronization is defined declaratively (e.g., via attributes), and the source generator handles all the event wiring and updates behind the scenes.
API breakdown
How It Could Work:
[SyncWithModel(typeof(Model))] specifies that this ViewModel synchronizes with the Model class.
[SyncProperty("Name")] marks the name property for bidirectional synchronization with Model.Name.
[SyncCollection("Items")] marks the items collection for bidirectional synchronization with Model.Items.
The source generator could then:
Initialize name and items from the Model in the constructor.
Subscribe to PropertyChanged on the Model to update name.
Subscribe to CollectionChanged on both Model.Items and ViewModel.Items for two-way updates.
Generate the update logic with an isSyncing guard to prevent infinite loops.
Usage example
Hypothetical Example:
Here’s what I envision the code could look like with source generators:
Would the MVVM Community Toolkit team consider adding this kind of source-generator-based synchronization? It would make the code much cleaner and more maintainable. If this is doable, what challenges might arise in implementing it? Alternatively, if there’s an existing way to achieve this with less boilerplate, I’d appreciate pointers or examples.
Help us help you
No, just wanted to propose this
The text was updated successfully, but these errors were encountered:
Overview
I’m using the MVVM Community Toolkit to keep a ViewModel synchronized with a Model, handling both properties and collections. The
[ObservableProperty]
attribute already simplifiesINotifyPropertyChanged
implementation, but bidirectional synchronization between the ViewModel and Model still requires manually writing event handlers and update logic. This becomes repetitive and prone to errors, especially with multiple properties or collections.Current Code:
Here’s my current ViewModel implementation, which synchronizes a
Name
property and anItems
collection with aModel
:Issue:
While functional, this code involves a lot of boilerplate:
PropertyChanged
andCollectionChanged
.isSyncing
flag to avoid infinite loops.Question:
Could the MVVM Community Toolkit leverage source generators to eliminate this boilerplate? I’d love to see a solution where synchronization is defined declaratively (e.g., via attributes), and the source generator handles all the event wiring and updates behind the scenes.
API breakdown
How It Could Work:
[SyncWithModel(typeof(Model))]
specifies that this ViewModel synchronizes with theModel
class.[SyncProperty("Name")]
marks thename
property for bidirectional synchronization withModel.Name
.[SyncCollection("Items")]
marks theitems
collection for bidirectional synchronization withModel.Items
.The source generator could then:
name
anditems
from the Model in the constructor.PropertyChanged
on the Model to updatename
.CollectionChanged
on bothModel.Items
andViewModel.Items
for two-way updates.isSyncing
guard to prevent infinite loops.Usage example
Hypothetical Example:
Here’s what I envision the code could look like with source generators:
Breaking change?
No
Alternatives
None
Additional context
Would the MVVM Community Toolkit team consider adding this kind of source-generator-based synchronization? It would make the code much cleaner and more maintainable. If this is doable, what challenges might arise in implementing it? Alternatively, if there’s an existing way to achieve this with less boilerplate, I’d appreciate pointers or examples.
Help us help you
No, just wanted to propose this
The text was updated successfully, but these errors were encountered: