Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion - Make Blazor MVVM Friendly #16331

Closed
legistek opened this issue Mar 25, 2018 · 15 comments
Closed

Suggestion - Make Blazor MVVM Friendly #16331

legistek opened this issue Mar 25, 2018 · 15 comments
Labels
area-blazor Includes: Blazor, Razor Components

Comments

@legistek
Copy link

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.

@plamen-i
Copy link

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.

@danroth27
Copy link
Member

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.

@legistek
Copy link
Author

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.

@danroth27
Copy link
Member

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.

@touseefbsb
Copy link

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.

@legistek
Copy link
Author

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.

@touseefbsb
Copy link

@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.

@legistek
Copy link
Author

@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?

@mkArtakMSFT mkArtakMSFT transferred this issue from dotnet/blazor Oct 27, 2019
@mkArtakMSFT mkArtakMSFT added the area-blazor Includes: Blazor, Razor Components label Oct 27, 2019
@DanJBower
Copy link

@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
Copy link
Author

legistek commented Nov 29, 2019

@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.

@richbryant
Copy link

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.

@legistek
Copy link
Author

legistek commented Dec 9, 2019

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.

@richbryant
Copy link

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.

@legistek
Copy link
Author

legistek commented Dec 9, 2019

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.

@richbryant
Copy link

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.

@ghost ghost locked as resolved and limited conversation to collaborators Jan 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

No branches or pull requests

7 participants