Aspnetcore: Suggestion - Make Blazor MVVM Friendly

Created on 25 Mar 2018  路  15Comments  路  Source: dotnet/aspnetcore

I know that code re-use between desktop/mobile and web is not necessarily the top priority for this project, but there seems to be tremendous opportunity here for just that and I don't think it would detract much - if any - from the main vision.

The most obvious addition would be to have an ICommand Command property in BlazorComponents and tie it to onclick. This is already doable by making my own MVVMButton component and it really works great:

<button @onclick(() =>
        {
            this.Command?.Execute(null);
        })>
    @Label
</button>

@functions {
    private ICommand _command;
    public ICommand Command
    {
        get => _command;
        set => _command = value;
    }

    public string Label { get; set; }
}

Even this one step is a huge leap toward re-using view models between Blazor and WPF/UWP/Xamarin.Forms apps.

Wondering if this is an idea the team would be interested in exploring and if so I'd be interested in starting a fork and contributing.

area-blazor

Most helpful comment

@danroth27 another conversation made me think of this thread. As you've said and I agree it's good for Blazor to be flexible. However what do you think about a couple of small, targeted items -

(1) Add ICommand Command and object CommandParameter properties to BlazorComponent and have button, checkbox, and maybe a few other components invoke Command with CommandParameter when they're clicked
(2) Have BlazorComponent implement INotifyPropertyChanged and add a protected virtual void OnPropertyChanged method for overriding and calling by internal setters.

These would go a really long way, most importantly avoiding us having to make a derived version of every common component just to implement an MVVM pattern.

Would you consider a PR for just these?

All 15 comments

Even with this approach you will continue to write ASP.NET Razor-style code.

For MVVM support and complete code reuse (XAML/MVVM), see https://github.com/praeclarum/Ooui.

Our goal with Blazor is target a broad audience with Web developers, so we're specifically not targeting compatibility with WPF/UWP/Xamarin.Forms. We are also trying to give the you the flexibility to use the patterns you want without baking too much in the framework. So you should be able to implement MVVM patterns on top of Blazor's core concepts (much like you are doing already). It doesn't sound like you are blocked with this, and we don't plan to do more in this direction.

Hi Daniel - very true, you seem to have made this puppy more than flexible enough to handle MVVM and probably other patterns without backend changes. I won't pester you with PRs then but I will definitely start working on some MVVM-friendly components that build on your core work. In any event, well done and cheers.

I will definitely start working on some MVVM-friendly components that build on your core work

That sounds great! Let us know when you have something you'd folks to try out and we'd be happy to help promote.

would definitely apprecite any kind of MVVM stuff in blazor, if the framework itself doesnot make this happen within the framework and someone else decides to fork blazor and make it mvvm that would also be a good option. mvvm is not limited to uwp/wpf apps it is pretty much everywhere these days even in web frameworks most frameworks follow this approach as it has obvious benefits for testing and seperation of concerns.

I don't imagine forking will be necessary. Daniel is right, they are making it extremely versatile. I'm looking at Blazor principally as a bridge between C# and the DOM. The full blown frameowrks are going to be built on top of this, not instead of.

@pmoorelegistek maybe you are right that full frameworks maybe built on top of this but I hope Microsoft themselves make a MVVM framework on top of this bcz that would be officially supported and more stable for developers to just use it built into Visual studio instead of tracking a community framework and hoping it follows latest standards.

@danroth27 another conversation made me think of this thread. As you've said and I agree it's good for Blazor to be flexible. However what do you think about a couple of small, targeted items -

(1) Add ICommand Command and object CommandParameter properties to BlazorComponent and have button, checkbox, and maybe a few other components invoke Command with CommandParameter when they're clicked
(2) Have BlazorComponent implement INotifyPropertyChanged and add a protected virtual void OnPropertyChanged method for overriding and calling by internal setters.

These would go a really long way, most importantly avoiding us having to make a derived version of every common component just to implement an MVVM pattern.

Would you consider a PR for just these?

@legistek Was there any furter discussion on implementing these? I'm just starting out with Blazor and was looking for the best way of implementing MVVM within my blazor web app.

@legistek Was there any furter discussion on implementing these? I'm just starting out with Blazor and was looking for the best way of implementing MVVM within my blazor web app.

Unfortunately no, I've not been able to drum up interest in this among the project maintainers.

Having worked on this extensively myself (on a proprietary project, I'm afraid), the other key item you really need besides use of INotifyPropertyChanged is data binding and something equivalent to dependency properties. The main problem is knowing when to trigger render tree refresh based on view model property updates. You can do something simple like define a ViewModel property on all your components and subscribe to PropertyChanged if the view model implements INPC, and if so call StateHasCHanged() in the handler, but this only gets you one level of property change detection - for example, you could bind to Person.Name if your ViewModel was set to a Person, but you couldn't bind to Person.Father.Name easily unless your view models already accounted for this issue.

Also the Razor syntax is not particularly friendly to a property binding mechanism. All you can do is assign values directly to component properties, so you can't really do something like:

<MVVMButton Command=@Binding("MyCommand")>

unless you defined the Command property with a Binding data type rather than an ICommand, which then makes it awkward to access in C# code.

Sadly my suggestion that Blazor support markup extensions to permit this kind of syntax was pretty much summarily shot down.

If we want MVVM in Blazor I think the best bet is to build out a Xamarin Forms backend such as I did in my prototype. I wish I had more time to work on it.

I don't know if anyone's still interested but this sort-of works using ReactiveUI, which I admit is not to everyone's taste but it's still a decent example.

I'd like a nicer way to execute ReactiveCommand but luckily, Mladen has allowed me to fork Blazorise, which would provide a beautiful set of components implementing RxUI binding and ReactiveCommands.

The problem is change detection. As far as I can tell, Blazor refreshes components if they are subject to some kind of user input event. That works great until you want a component to update in response to action taken on another component (for example, you have two independent components bound to the same view model). To support that you have to either manually rig up property change subscriptions (a disaster waiting to happen) or implement a true data binding mechanism.

RxUI does this by simply having both components subscribe to an observable - it's never been a disaster waiting to happen on any other platform yet.

RxUI does this by simply having both components subscribe to an observable

Well ok but that's completely antithetical to the MVVM pattern.

it's never been a disaster waiting to happen on any other platform yet.

Then you're more fortunate than I am. I inherited an Angular project with observables up the ying yang and calling it spaghetti code would have been an insult to spaghetti.

Rx.js can be a pain. Rx.Net (and especially ReactiveUI) much less so. What's nice about RxUI is that it's truly, truly cross-platform. WPF? Sure. Winforms? Totally. Xamarin? Absolutely. Avalonia? Yup. Cool new stuff like Uno? Right there, because why not?

I also disagree that it's antithetical to the MVVM pattern. An observable in this case is merely a property of a ViewModel. Multiple bindings of a single property are common as all hell, otherwise nothing would work.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

farhadibehnam picture farhadibehnam  路  3Comments

FourLeafClover picture FourLeafClover  路  3Comments

snebjorn picture snebjorn  路  3Comments

ipinak picture ipinak  路  3Comments

markrendle picture markrendle  路  3Comments