RolandPheasant / DynamicData.Snippets

'101 samples' of dynamic data and rx in action

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

AutoRefresh can't work with a data source defined by interface

jkears opened this issue · comments

I am creating an UI Builder for Blazor and in order to update Blazor when changes occur to the backing ViewModel. In particular, I would like to use the property 'Position' changes within the ComponentViewModel base class. The Position property is updated via a separate Drag/Drop service.

I have an interface for ComponentViewModel called IComponentViewModel which is how I've defined my backing DD SourceList.

private SourceList<IComponentViewModel> _componentViewModelSourceList = new SourceList<IComponentViewModel>();
private ReadOnlyObservableCollection<IComponentViewModel>? _childComponents; 

public CompositeDisposable? Disposables { get; set; }
public IObservable<Position> NewPosition { get; }

Within the constructor I am binding the SourceList to a ReadOnlyObservableCollection 'ChildComponents' as follows, which works great!

            Disposables = new CompositeDisposable();

            Disposables.Add(_componentViewModelSourceList
                .Connect() 
                .ObserveOn(RxApp.MainThreadScheduler) 
                .Bind(out _childComponents)
                .DisposeMany()
                .Subscribe());

Also within the constructor I am attempting to AutoRefresh on changes to the 'Position' property within IComponentViewModel as follows...

var NewPosition = _componentViewModelSourceList.Connect()

             // Subscribe to changes on Position property.
             .AutoRefresh(x => x.Position)
             .Select(); 

however I receive the following error.

CS0311: The type '...IComponentViewModel' cannot be used as a type parameter 'TObject' in the generic method 'IObservableListEx.AutoRefresh<TObject, TProperty> ...'

If I change the SourceList to be the ComponentViewModel then the error goes away, however I would prefer (if possible) to keep it as IComponentViewModel.

Is there some way to add an operator to cast the IObservablable ChangeSet so that I can apply the AutoRefresh with the interface approach.

Thank you in advance.

Do you need to inherit INPC on the interface as well as implementing it on the implementation?

Hi Roland, a pleasure to make your acquaintance.

Yes, ideally, but so far it may not be needed as in my current design, each specialized ComponentViewModel does not currently have any additional properties that I would need to apply AutoRefresh, but may in the future, so it would be ideal if I could AutoRefresh on any property within either ComponentViewModel as well as any property in the SpecializedComponentViewModel.

At a very high-level, this is the relationship.

Specialized1ComponentViewModel which inherits from ComponentViewModel ==> Binds to Specialized1BlazorViewComponent
..
SpecializedXComponentViewModel which inherits from ComponentViewModel ==> Binds to SpecializedXBlazorViewComponent

The actual Blazor component's Type information is held within the SpecializedComponentViewModel, which is how different components are rendered within the Designer Canvas.

This is really interesting and seems to be the exact opposite of reactivemarbles/DynamicData#512 which for historic reasons has a different behaviour.