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

Native Support of MVVM Pattern #434

Open
AhmedAbuelnour opened this issue Mar 11, 2019 · 8 comments
Open

Native Support of MVVM Pattern #434

AhmedAbuelnour opened this issue Mar 11, 2019 · 8 comments
Labels
Design Discussion Ongoing discussion about design without consensus Enhancement Requested Product code improvement that does NOT require public API changes/additions
Milestone

Comments

@AhmedAbuelnour
Copy link

I really wish to see that one day, we have a native support for MVVM Pattern in all XAML based applications (Xamarin , UWP , and WPF) like you did in ASP.NET MVC

We need a native support of MVVM Pattern to make it more clean and well structured and no need for injecting tons of services and code editting to set up the project to be ready to be used.

@stevenbrix stevenbrix added Enhancement Requested Product code improvement that does NOT require public API changes/additions Design Discussion Ongoing discussion about design without consensus labels Mar 11, 2019
@stevenbrix stevenbrix modified the milestones: 3.0, Future Mar 11, 2019
@dotMorten
Copy link
Contributor

There's all the key MVVM ingredients needed: INotifyPropertyChanged, INotifyCollectionChanged, ICommand, and binding support all out of the box.

Could you explain what you mean by "native support" ?

@AhmedAbuelnour
Copy link
Author

@dotMorten i meant built-in MVVM Pattern, i know there are some useful classes to make your application MVVM based, but what i mean a ready made MVVM structure of the project, and simplify the process of binding like a command for instance. and the validation process and the navigation between the windows or pages

no need for injecting libraries that change their code every release, that have tons of bugs and messy code structure

ASP.NET MVC for example, is a perfect example for what i mean.

@dotMorten
Copy link
Contributor

@AhmedAbuelnour Is there any reason you can't just use Prism, MVVMLight, MvvmCross etc? Why would it need to be dictated by the platform?
IMHO 'patterns' can't really be built-in, as they are just that: "a pattern" that you choose to follow - It's not an API. The APIs for doing MVVM is already there - in fact they are all the way down in .NET Standard which is awesome.
So I'm curious what sort of APIs specifically that you feel a lacking?

@AhmedAbuelnour
Copy link
Author

There are some lakes API with the following
What about direct binding with events and commands ?
what about simple navigation and carrying data with routing?

@dotMorten
Copy link
Contributor

Frame and NavigationService is already there in WPF, including forwarding data.

Command binding is also already there with ICommand and many controls having Command properties to bind to.

So am I right in saying you just want to be able to bind an event directly to a method? (similar to UWP's x:Bind method binding?)

@bigworld12
Copy link

this should be more like replacing wpf's Binding with UWP's x:Bind and unify the binding experience for both platforms

@trodent83
Copy link

@dotMorten
The use platforms Extension means basicly that the platform doesn't support the required funtionality, and you have first extend the platform.
Also all These third Party Tools have their limitations, and as they are third Party in some cases their usages are not allowed. Now if you have the experience you can rebuild them all for your own use but the fact that you have to means that it is missing.

Not just this but basicly the current binding implementation doesn't support input Validation hook, so basicly in the bindings you have to add explicitly rules for data Validation. Of Course there is a Workaround for this, but we are again at the Point where the platform doesn't support it out of the box.

And then we come to the really tricky part the command revalidation. There is currently no Default implementations to detect Content changes on Elements which are not present on the ViewModel Level, so if you want to use the commandparameter property of Control you have to still Mirror the value down to ViewModel Level, or you have hook in the CommandManager.RequerySuggested which is also not the best.

@daiplusplus
Copy link

daiplusplus commented Apr 18, 2021

I'd frame it not as "add 'native' support for MVVM" but more as: "please please please eliminate the tedium and repetitive (and error-prone, and brittle) work we need to do in order to implement MVVM".

A few things I can think of right now off the top-of-my-head:

  • Roslyn code-generation for INPC is not a perfect solution. A major shortcoming to Roslyn code-gen is the inability to tweak or edit the generated code - we can't even (easily) save a snapshot of the generated code in the main project because Roslyn code-gen by design saves the generated C# code to an in-memory store and not to disk (unlike the old XamlFileName.i.g.cs files).
  • It's unclear in WPF if the View (Window/Xaml) "owns" the ViewModel, or if the ViewModel "owns" the View, or if it's something else - this is made harder by the fact that different MVVM libraries have their own, often fundamentally different, ways of managing view lifetimes.
  • MVVM and DI go hand-in-hand - but we can't easily control the construction of Views such that we can correctly maintain state invariants.
    • i.e. what is the ordained way of passing a ViewModel into a WPF XAML View without having the View be in an invalid state?
  • WPF's App.xaml auto-generated Main method gets in the way of setting up IHost and DI containers. Overriding it is straightforward, but it's still another hoop to jump through.
  • ViewModels should try to be slightly more abstract than a view, so why do we have to use WPF-specific property types (like Visibility) instead of more general types? I know we can use a value-converter, but that's another hoop to jump through, and the XAML binding syntax for using a value-converter is painful (and value-converters are not strongly-typed).
  • Biggest request for MVVM: Let us put raw C# in a binding expression. Let's stop pretending that you want a middle-of-the-road syntax that accommodates VB.NET and C# developers and is XML-safe. VB.NET just isn't relevant anymore and the XAML markup editor could hide the CDATA delimiters or automatically XML-encode unsafe characters in binding expressions behind-the-scenes for us.
    • Here's some conceptually-simple tasks that XAML makes very difficult or tedious, and/or requires us to compromise our ViewModels and make them tightly-coupled to WPF and/or specific View XAML (remember the dream of being able to directly reuse ViewModel classes between WPF and ASP.NET MVC? hah)
    • Using {Binding ..., RelativeSource} and DataContext="" in separate properties on the same element is confusing.
  • WPF's Dispatcher and INPC event-handling logic is strange to WPF newcomers: when a property PropertyChanged it's reasonable to expect that the changed property's getter would be immediately invoked by the event-subscriber's event-handler, but Dispatcher (reasonably and rightfully so) defers accessing the property until later - however when it comes to writing unit and integration tests over ViewModels most of us will just access changed properties directly in the event-handler callback because it's significantly simpler, but this does cause a difference in behaviour that differs from in-app use and causes bugs to slip-through testing (and vice-versa: bugs that only appear in testing, not production).
  • Why are Dependency Properties still so awkward?
  • I imagine most of us (well, at least me) use our own hand-crafted T4 templates to generate the tedious parts of DI+MVVM for us (for example, here's mine), part of the problem is C# (not XAML)'s stranger rules, such as how we can't run code before a parent constructor; how there's no constructor inheritance; how we can't set a readonly field or property from a member function called from a constructor (which is a problem if the constructor exists in generated code: the partial keyword won't save us now), and so on...
    • Visual Studio's WPF project templates should come with a T4 template like mine in-box to handle VM generation for the user. But the T4 should be editable so users can tweak it as they see fit. T4 is amazing and it needs more love (I'm still waiting for syntax coloring for T4 in VS for 13 years now...)

Another problem with MVVM-in-practice is a lot of tutorials and whitepapers are too simplistic (e.g. singleton views with singleton viewmodels) and/or use static ViewModel locators. WPF needs more in-box samples that demonstrate best-practices with more complex (or rather: more realistic) project examples, such as how MVVM+DI can be used in a WPF application that creates multiple concurrent windows (which can be of the same Window XAML class) all with plenty of child views, dialogs, and more.


Edit:

Now that I think about it, I'm actually starting to feel a disdain for MVVM because it has a lot of inherent problems (difficult to compose; the inevitability of having to use a common BaseViewModel class; untyped PropertyChanged events; the direction of data-flow is undefined and it's easy to get stuck in reentrant callbacks; mutually-dependent properties are also another programming-tarpit; when I look at how Redux and React don't have these problems (because of their strictly-enforced unidirectional data-flow) I get depressed because WPF might have had something better than Redux/React by now if Microsoft didn't stop significant investment in WPF after .NET Framework 4.0).

I know a Redux/React-style refreshing of the entire UI state (yes, I know it's optimized) wouldn't scale for data-heavy scenarios, but I am really drawn towards the idea of enforced unidirectional data-flow - which would be straightforward to implement in MVVMs if we could have succint "split" bindings in XAML such that the Property-Getter is used for display, but any changes back to the ViewModel have to go through an action-dispatch system like Redux/React - the problem is doing this correctly would be even more tedious than bidrectional INPC because we'd have to manually define all those separate Actions as separate types and members (or settle for something weakly-typed and without compile-time assurances of correctness).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Discussion Ongoing discussion about design without consensus Enhancement Requested Product code improvement that does NOT require public API changes/additions
Projects
None yet
Development

No branches or pull requests

6 participants