Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Cascading BindingContext #53

Open
hillin opened this issue Jun 4, 2021 · 7 comments
Open

Cascading BindingContext #53

hillin opened this issue Jun 4, 2021 · 7 comments
Labels
type: feature New feature or enhancement

Comments

@hillin
Copy link
Contributor

hillin commented Jun 4, 2021

Is there a way to have cascading BindingContext?
Say we have two components:

class ParentComponent: MvvmComponentBase<ParentViewModel> {
    ChildComponent Child;
}
class ChildComponent: MvvmComponentBase<ChildViewModel> { }
class ParentViewModel: ViewModelBase {
    ChildViewModel Child { get; }
}
class ChildViewModel: ViewModelBase {}

Now I would like to bind the BindingContext of the Child component in the ParentComponent to the Child property of the ParentViewModel instance, which is automatically resolved for the ParentComponent. However it seems the view model is always resolved in the component's constructor via DI, and we don't have a public BindingContext property to override.

@hillin
Copy link
Contributor Author

hillin commented Jun 4, 2021

One way is to register the view models as Scoped, which is generally not a good idea because it forces all the component instances of the same type to share a single view model instance.
I also can always create a new property on the ChildViewModel and bind to that property instead of the BindingContext, but this kind of use case is very common and I think it should be supported by any MVVM framework.

One possible approach is make the BindingContext property public and [Parameter], and make its auto-resolve lazy, so the parent component have a chance to specify the child component's BindingContext as a parameter, before it's being used for the first time.

@klemmchr
Copy link
Owner

klemmchr commented Jun 4, 2021

One possible approach is make the BindingContext property public and [Parameter], and make its auto-resolve lazy, so the parent component have a chance to specify the child component's BindingContext as a parameter, before it's being used for the first time.

Sounds good to me, would love to see a PR with this. Otherwise, I'm gonna implement this.

@hillin
Copy link
Contributor Author

hillin commented Jun 4, 2021

Right now I'm playing with this idea, but it raises some questions:

  • Should the auto-resolve be lazy or should we keep the SetBindingContext call in the OnInitialized method (i.e. the BindingContext can only be set externally before the component is initialized)?
  • If we set the BindingContext after the component is initialized, should the OnInitialized and OnInitializedAsync be called on the new BindingContext? Same goes to all other lifecycle methods.
  • Is the BindingContext bindable? If it's changed, should we update all the bindings in the component immediately?

@klemmchr
Copy link
Owner

klemmchr commented Jun 6, 2021

Should the auto-resolve be lazy or should we keep the SetBindingContext call in the OnInitialized method (i.e. the BindingContext can only be set externally before the component is initialized)?

As of now, the BindingContext is only resolved via DI if there is no binding context present. That would mean that making the property public should be enough to resolve this problem. This way, the lifecycle methods also get called on the right context right away.

Is the BindingContext bindable? If it's changed, should we update all the bindings in the component immediately?

I would argue against the possibility to change the binding context since it would open some potential loop holes. The binding context should be read only once set.

@hillin
Copy link
Contributor Author

hillin commented Jun 6, 2021

As of now, the BindingContext is only resolved via DI if there is no binding context present. That would mean that making the property public should be enough to resolve this problem. This way, the lifecycle methods also get called on the right context right away.

If I'm not mistaken, the view model is set right in the constructor, so it's always present.

I would argue against the possibility to change the binding context since it would open some potential loop holes. The binding context should be read only once set.

For example WPF allows you to change DataContext, you can even bind something to it. But I agree it's not a must-have and for simplicity it's a reasonable design choice to not allow changing the view model.

@klemmchr
Copy link
Owner

klemmchr commented Jun 6, 2021

If I'm not mistaken, the view model is set right in the constructor, so it's always present.

This only applies for the internal constructor that is used for testing. This constructor serves no purpose besides that. When inheriting from MvvmComponentBase<T> the public constructor will be used. And then the BindingContext will be resolved on init, if not present.

For example WPF allows you to change DataContext, you can even bind something to it. But I agree it's not a must-have and for simplicity it's a reasonable design choice to not allow changing the view model.

It would be a nice to have thingie, however upon changing the BindingContext all bindings would need to be redone which could be a bit messy (but doable IMO).

@hillin
Copy link
Contributor Author

hillin commented Jun 7, 2021

This only applies for the internal constructor that is used for testing. This constructor serves no purpose besides that. When inheriting from MvvmComponentBase<T> the public constructor will be used. And then the BindingContext will be resolved on init, if not present.

Right, I misread the code. So yeah, I agree for now making BindingContext public could have the job done (and maybe a little protection mechanism to prevent it from changing after OnInitialized).

@klemmchr klemmchr added the type: feature New feature or enhancement label Apr 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: feature New feature or enhancement
Projects
None yet
Development

No branches or pull requests

2 participants