Navigation - WPF MVVM TUTORIAL #5
HTML-код
- Опубликовано: 2 июн 2024
- Learn about implementing navigation in an MVVM application. Navigation in WPF is implemented via a store, which is a single instance object that holds application state. The single navigation store is used throughout the application in order to update the current view.
In this series, I demonstrate all the key components of a WPF MVVM application. This series will lay the foundations for building your own application.
TIMESTAMPS:
0:00 - Introduction
0:47 - Implementing the NavigationStore
3:17 - Mapping View Models to Views
4:49 - Implementing the NavigateCommand
5:45 - Notifying CurrentViewModel Changes
7:06 - Abstracting the NavigateCommand
10:15 - Implementing the NavigationService
13:39 - Updating Reservation Listing Data
15:04 - Conclusion
NAVIGATION SERIES: • WPF Navigation
SOURCE CODE: github.com/SingletonSean/rese...
OTHER LINKS:
Become a Member: / @singletonsean
Donations: www.paypal.com/biz/fund?id=UB... - Наука
Hi Sean - just wanted to say thank you for this series. It's been really helpful for me, and I like your fast pace. I watch the video through first without trying to type any code. This gives me a high-level overview of what we're going to do. Then I use pause heaps as I type the code, and finally watch it through again and add comments. Great stuff, and thanks again 🙂
Great course, thank You for doing that!
Man this is so useful gotta admit thoe u are going a lil to fast throught that so I always watch these videos 2 times, I came from java so not 100 percent practised and familiar with c# syntax, thanks although
My brain literally hurts after this video^^. But well explained :)
Agreed, it is complex! I'm looking forward to using the built-in navigation in .NET MAUI.
Great video! Btw, how did you move the constructor to the end of the class? (at 2:55) Is it an auto-format setting in Visual Studio? I'm just curious to know.
I've been using WPF for a while now and have to saw, Stores are a completely new thing to me! .. not sure if I have been living under a rock, but I have not heard of them. Can I ask where you learnt them from?
thank you bro for this useful content.
Hey SingleTonSean,
first of all Thank you very much for your tutorials. I implemented your navigation from Video #5 to my project. Afterwards i tried to implement also a Navigation bar, recommended in on of your other videos. But it seems you do it there slightly different.
What do i have to do, to implement a navigation bar in this project ? I have the problem that only 1x Viewmodel is allowed at the same time. If I place the NavigationBarViewModel in the StartUp, it can only see the navbar, and its working for one click. Afterwards the other ViewModel is Loaded and i just see a non working navbar.
Any Ideas ? Thank you very much in advance.
BR Philip
Greate Video! just a question, is there a way to determine what User Control is currently on view?
Hey, great stuff! But why do you not use INotifyPropertyChangened in your Stores? I do use it in nearly all my BackendClasses is there any Reason not to do that?
Good stuff man! I might be being paranoid, but I think that the event subscriptions will cause you some memory leaks since you are creating new view models each time you navigate.
Thanks Jackson! Which event subscriptions were you referring to?
Very useful. I am reviewing the approach in this series against using Prism.
Thanks Ian! I've heard lots of people have enjoyed Prism's navigation. I haven't tried Prism so I won't leave my opinion, although I've browsed the docs a bit 🤭
@@SingletonSean Any chance of a video demonstrating the use of DTO's please?
Hey Ian, I actually kind of demonstrate it in part 6 of this series. Specifically, I use a DTO to map reservations to the reservation database table. I typically use DTOs whenever interfacing with an external data source (databases, APIs, etc.).
@@SingletonSean Many thanks Sean!
Do you have any idea why my data in listing view model is not showing up since I changed from simple binding to Data Template?
Hi Sean! Can you develop the code to navigate from ListViewModel to DetailViewModel and back with Factories? I'm stuck because I'm facing cross dependency: A ListViewModel needs a NavigationService for the DetailViewModel, so in the NavigationService constructor I pass a DetailViewModelFactory as a parameter, which as a method to create a DetailViewModel.
Since the DetailViewModel needs to navigate back to ListViewModel, I need to pass a NavigationService for the ListViewModel, so with a ListViewModelFactory which needs the NavigationService for the DetailViewModel that I'm trying to initalize fiirst... How would you solve this? Is it possible with constructor dependency? I hope it's clear, I'm italian native speaker ;) Thanks and keep it up!!!
Wondering how to put multiple views into one main view, however, on single page. With that I mean to create something like a dashboard, for example split screen into 4 parts and each part would be connected to a different view. Is it possible to pass multiple data contexts to the main view at once ?
Hey Maximvs, that's a good question! For that, I usually have a view (such as ) that is made up of many UI components (such as , , etc.). Then, I'd have a view model (such as DashboardViewModel) that contains view model properties for the items in the dashboard (such as DashboardItemViewModel1, etc.). Finally, I can set the DataContext on the DashboardItem UI components as a binding to the DashboardItemViewModels.
I wish I had an example for this! Let me know if this helps.
I did exactly like you did but my view isn't changing when I click the navigate button (the current view model changes but no navigation)
Which deign pattern did u use? Factory? It is a little difficult for me as a beginner😢
When you create your functions to create view models, what is the benefit of passing the functions into the constructors of the VM's? Couldn't you create the function in the VM itself and pass that in?
Hey Jeremy! I'm not sure I fully grasp your question, but I prefer to pass things through constructors to try and keep things loosely coupled. That might not actually matter here, and the other idea you raised might be a better option. Which view model were you referring to?
With all the prop drilling going on, I'm hoping on some IoC dependency injection in the next chapters :)
Is there any good reason to do not use builtin NavigationService and Pages if you want to make navigation/browser style application?
Hey Besik, I've never been on a project that uses the built-in browser style navigation. I think that navigation is specifically for browser style apps, so I think there's definitely a good reason to use it there.
Hi I am trying to navigate to two different viewmodels from a master viewmodel. but both buttons go to the same viewmodel. can you give a suggestion.
Me too .. Same Issue
Hi, Great tutorial but I have some problem here, I get two separate windows when I run the app - one window is the main window and the second is the reservation window.. what can be the problem?
Thanks Yulia! For that issue, simply go into your App.xaml and remove the property StartupUri="MainWindow.xaml"
Thank you
hello, i have a question, i have a button that doesn't belong to any of the Views, its outside it, but i want to bind it to another viewmodel, is it possible to do so? basically having buttons binding to a viewmodel and others to another viewmodel.
Hey Yakin! It might be possible somehow, but I'm not sure if it'd be a good idea. I think your view models should line up with the structure of your views. That said, I'd either build a view model for your view with the lonely button, or find a way to move the button into the view with the desired view model.
Sean - your content is good and you do a good job of explaining things, BUT you go WAY to fast. I have to pause the video so often to catch up typing, it's affecting the flow of how your audio and the teaching you're trying to accomplish.
This is so true.
Do you have a plugin installed for automation code formatting? If so what's it called?
Hi Meddler, I use XAML Styler. It's awesome!
marketplace.visualstudio.com/items?itemName=TeamXavalon.XAMLStyler
@@SingletonSean Thanks for that, and thank so much for your exceptional videos, they've been indispensable for me!
Hi Sean! At 9:49 you created two functions: CreateMakeReservationViewModel() and CreateReservationViewModel().
However, To make the first ViewModel, you need to use the second function
and at the same time, to make the second ViewModel, you need to use the first function.
Doesn't this create a never ending loop? I'm so confused about how this works
if you follow the instances to the navigateCommand Execute function you can see that the other func(delegate) is only called when the Execute function is called( in other words , the other function is called when the make Reservation button or the Cancel one is pressed , thus creating a new ViewModel instance each time).
@@smoke12785 Yup, we are not calling it right away!
The delegates/functions to create ViewModels are not being called right away
Hello. At 7:02 i get an error as my OnCurrentViewModelChanged() has to return Action instead of void somehow. Using .net core 3. Would be glad if you cuold help me!
You might set OnCurrentViewModelChanged() but you have to give pointer of the method only so remove the "()" after OnCurrentViewModelChanged.
like : _navigationStore.CurrentViewModelChanged += OnCurrentViewModelChanged;
Everything worked to this point but @ 4:48 Getting the following errors vms is undeclared namespace, vms not defined, ReservationListingViewModel & MakeReservationViewModel is not supported in a WPF project :(
Its crazy that you can handle all the inheritance thing in your brain so you can express that with code
"We want our View to be determined by whatever the current ViewModel value is..." So is this what is considered a ViewModel-first approach?
Can you make a tutorial, how to open new windows using mvvm pattern?
Your videos are great, and I really like it!
Thanks Sunshin! I think this tutorial might be helpful: ruclips.net/video/M8BAIq0yoy8/видео.html
I'm already member but I can't watch the members videos .. help please..
Hi Ali, you might have mixed up subscriptions vs. memberships. Being a member implies that you've purchased a monthly membership to the channel, as mentioned here: ruclips.net/channel/UC7X9mQ_XtTYWzr9Tf_NYcIgjoin
If you're interested in joining and supporting the channel, that'd be great and you'll be able to see all the videos! If not, no worries, all the videos that are currently "members only" will eventually be released publicly.
@@SingletonSean Thank you very much sir for the answer.. and thanks again for your valuable efforts.. I wish you more progress..
I think I missed the GetAllReservations method somewherew along the way.... 14:25
It was there for sure, but it happened in episode 2:
ruclips.net/video/UQOi48H_84s/видео.html
The change is also present in the github repo:
github.com/SingletonSean/reservoom/commit/36f7b9ed519489ebb9806e04229dd02693e8c90e#diff-a193a2120c87dad8c56b83b6aee117287f09b4fb4c2c98d42f76eec0d2dce85cL30
at 1:44 you said "we only want one we navigation store we don't want to instantiate this multiple times ", why do we not use static ?, this is been confusing me the whole navigation playlist, really appreciate the response ~ fellow noob here
Hey Iwky, that's a great question and I've actually gotten this question in another video! Overall, you could make it static, as long you're comfortable with the implications of static classes. This is my response from other comment threads:
I've actually seen frameworks do this. I think we'd have to consider the drawbacks of static classes.
1. We can't leverage polymorphism with static classes. In other words, static classes cannot implement an interface or extend a base class. For example, in my navigation series, I create a "ModalNavigationStore" that controls navigation in a modal. To promote reusability, I extract an "INavigationStore" interface that the NavigationStore and ModalNavigationStore both implement. If NavigationStore were static, it would not be able to implement this interface.
2. After reading point #1, you're probably thinking: "how about we make it a Singleton, which can leverage polymorphism?" This is much more realistic, but this means that we could only have one NavigationStore instance. What if we wanted multiple NavigationStores so that we could have multiple "sections" of navigation in our application? We wouldn't be able to do this with our single NavigationStore instance. This issue also applies to a static NavigationStore.
3. Lastly, I feel like unit testing is more difficult when depending on a static class. The static class causes tight coupling, and we can't mock the static class. Of course, not everyone team is big on unit testing, so this drawback might not apply to every application.
Perhaps these limitations of static classes aren't an issue for your application. In fact, all of the points I just made could be interpreted as a YAGNI ("you ain't gonna need it"). However, even though an application might not suffer from these drawbacks, I still think it's worth putting in the extra 1% of effort to pass the NavigationStore around rather than making it static.
Anyways, let me know if you have any questions about this Iwky. I hope this was helpful! Thanks for the question.
@@SingletonSean Thank you for explaining that sean
How to get the source code for this video?
Why? Window must be the root of the tree. Cannot add Window as a child of Visual
Great videos, but presented at Mach one!
I sorta get it, but.. what a cluster
You know a lot but you do not explain concepts
stated good but awful coding at the end, awful
Hey Aharon - sorry about that. I'm interested if you'd want to expand on this. Anyways, I hope the core topics from this video are still valuable. Certainly implement or code this in a more elegant way if possible!
Hi, at 7:57 can I implement the Execute() method like this?
public override void Execute(object? parameter)
{
if (_navigationStore.CurrentViewModel is ReservationListingViewModel)
_navigationStore.CurrentViewModel = new MakeReservationViewModel(_hotel, _navigationStore);
else if (_navigationStore.CurrentViewModel is MakeReservationViewModel)
_navigationStore.CurrentViewModel = new ReservationListingViewModel(_hotel, _navigationStore);
}
I check if CurrentViewModel is of type ReservationListingViewModel or MakeReservationViewModel
and then I reassign CurrentViewModel to the opposite instance. The app work perfectly and I think this way is very straightforward.:)
@SingletonSean Look over the issue below. I put my MainWindow.xaml back to exactly how it was at the start of this video (after taking a screenshot so I would have what I had before when the error was there) and then I tried again to follow. the one thing I did different than you did in your video was when I had the DataContext on the like you did at the start was the compiler wasn't like that so I took the advice on fixing that and it created the xmlns:viewmodels declaration for me along with a d: for a Data Context I'm not real sure what was going on in that but I went with it. Then, I changed where it put viewmodels as the namespace mapping to vms like you had it and I ultimately deleted the line where it added d: whatever. Then I went with what you did in the video and it works. I've compared now to the screenshot of what I had before and I haven't seen a difference. At this point, I'm just happy that it works and I can move forward so screw it. I probably will become a member based on how great your advice is. I like that you are a fan of decoupling and, judging from your replies to some of the comments below, you've obviously put some thought into why you did what you did. My first thought, for example (like the user lwky below), when you said "you only want one of these," was we're going to use a static class.... I'm not a big fan of static classes so I was took a second to organize my thoughts and how I was going to argue against you doing that in this comment... And lo and behold, you took that left turn on me and instantiated the thing in the app class without using static. I like your style!
Hey Madi, that is an interesting issue! You should be okay without specifying DataContext on the since WPF will pass down the DataContext automatically. I'm glad the solution in this video solved your issue!
I completely agree with your take on static classes and traditional singletons. I've been on so many projects that relied on singletons and they were soooo difficult to maintain and track bugs in. Now with the "built-in" dependency injection since .NET Core, I'm hoping projects will lean more in the direction of decoupling apps!