Google Analytics
Thursday, December 15, 2011
I am adding the module now to the shell. I'm looking at the UI Composition QuickStart in the guidance to get an idea of how to start. I want to have a main region and within that a tab region that I can add a tab to.
Started by adding TabControl and TabItem template to the shell. Had to work out the fact that I didn't need the Silverlight adapter and other related markup.
Added the module project as a simple class library and added the Views directory to it.
Added the UserManagementModule class as a normal class. It implements IModule and its constructor takes a UnityContainer and RegionManager interfaces. In the Initialize() method we Register the UserManagement view with the tabRegion on the shell. So... we need to add the UserManagement View.
We add that to the Views directory as a UserControl. I also just added a textBlock in the view to indicate that it is loaded. I had to explicitly override ConfigureModuleCatalog in the Bootstrapper and add the UserManagementModule to the catalog for now. Like I said before, I want to use the directory discovery method to get the modules, but we are taking baby steps here.
So when I run this now an odd thing happens: I get a shell with two tabs. The first has no content. I think that it has to do with the fact that I am doing view injection rather than the view discovery of the QuickStart for the main region and I am getting the two methods crossed. The second tab has my content. It doesn't have the name on the tab, which is supposed to be bound to the View's ViewName property. Took me a few minutes to realize that I need to put that in the ViewModel object for the view. (Duh! Isn't that how all this is supposed to work in the first place?) So Next I will be adding the ViewModel for the UserManagement view, adding the ViewName property of that, and seeing if it gets displayed in my tab.
The UserManagementModel gets added as a plain class that implements INotifyPropertyChanged, so it has a PropertyChanged event. The model is injected in the constructor of the view. Then we set the dataContext of the view to the model. This is a change from the MVP architecture we have used in the past where an interface to the view was injected into the constructor of a presenter and the view basically had no knowledge of its presenter. With MVVM the view will actively subscribe to events from the model and bind to its collections and commands. I'm wondering at this point if I should create an interface for the ViewModel, but I don't see why at the moment so leaving as is.
WPF TabControl done differently than the Silverlight example in QuickStart, and that is what was giving me the two tabs and not correctly showing the view name on the tab as I wanted. I had to bind to Content.DataContext.ViewName rather than just ViewName as described in the QuickStart or DataContext.ViewName as some examples on the internets showed.
Now I need to activate the tab. Hook up some dataService and bind users to a listControl. Add a second tab and probably localize region names.
Wednesday, December 14, 2011
Prism, WPF and My First Module
To start off with, I would like to create my shell, bootstrapper and first module. I'm choosing the User Management interface of our current project as that initial module, though to begin with all I plan on doing is loading a tab control into the main region. My current plan is to create a shell with a main menu and a main content region. One of the menu items will be Administration and one of the sub-menus under that will be User Management. When the user selects User Management the tab control with the title User Management should load in the main content region.
At first the menu content will just be static, but it would be nice if I could dynamically add the menu item at runtime. I'm not sure that I can specify that the User Management module should load OnDemand rather than OnStartup and still be able to populate the menu. That is one of the things to figure out. I am going to try using populating the module catalog with directory discovery. Another option I think we COULD possibly use is a ConfigurationModuleCatalog. In either case we just need to make sure we are doing thigns securely so that no one can drop in a rogue assembly that could be discovered and loaded. Also I would like to be able to "unload" the tab control and not just hide it so that the control is not using overhead memory. That is another thing to experiment with.
Then the user management view is probably going to be composed of two related views: a Roles control and a Users control. Each of those controls will have a list of their respective model data as well as a Detail view for selected items. So my next task will be to wire up the model to correctly display the system's roles and users as well as the command(s) for selecting an oject from the list and showing its properties in the details view.
In the Users control there will be commands for adding, editing and disabling users. (There is no deleting of created users.) This will give me a chance to do error handling and business rules regarding the users (like password strength and that the default Admin user cannot be disabled).
For each of the controls there are a couple view-related features like the refresh and filter commands. They may be interesting to experiment with in the MVVM framework, but aren't terribly important.
Finally, there is the relatively simple task of adding and removing users from roles, which will give me the opportunity to see how my two controls will communicate with each other.
So on to creating my application and creating the shell and bootstrapper.
Following the walk-throughs for Prism Guidance:
In Visual Studio 2010: New Project > Windows > WPF Application. I'm naming it AdjudicationPoC.
Change MainWindow.xaml to Shell.xaml. VS changes the code-behind name to Shell.xaml.cs, but need to change the actual class name and constructor and also go into App.xaml and remove the startupURI attribute. The Bootstrapper will handle what starts, and in fact we can just go in now to the App.xaml.cs code-behind and override the OnStartup method to create and run our Bootstrapper. Of course, now VS is going to bitch that we don't have a Bootstrapper class so let's add that to the project now too.
Now I'm going to make the executive decision to use Unity as our IoC container, so our Bootstrapper is going to inherit from UnityBootstrapper, and to do this we need to include the Microsoft Prism Libraries. Again following the walk-through in the Guidance I created a Libraries folder in my solution folder. I copied in the Prism libraries (I'm just leaving out the MEF libraries, since, at least for now, I won't be using them), and added the references to my project. Our development team usually keeps our 3rd party libraries outside the solution, so that will probably change, but good for now.
After adding those references I just need to override the CreateShell and InitializeShell methodsof the UnityBootstrapper to create an instance of the Shell, set it as the MainWindow of our App and show it. I'm sort of not crazy about the reference to the App here, since it would be nice to be able to unit test the bootstrapper (and, more importantly, automate that test) without it. It isn't doing much at the moment, plus I may see what MSTest can do for me in order to really test it. That's for tomorrow.
plus I may see what MSTest can do for me in order to really test it. That's for tomorrow.
At first the menu content will just be static, but it would be nice if I could dynamically add the menu item at runtime. I'm not sure that I can specify that the User Management module should load OnDemand rather than OnStartup and still be able to populate the menu. That is one of the things to figure out. I am going to try using populating the module catalog with directory discovery. Another option I think we COULD possibly use is a ConfigurationModuleCatalog. In either case we just need to make sure we are doing thigns securely so that no one can drop in a rogue assembly that could be discovered and loaded. Also I would like to be able to "unload" the tab control and not just hide it so that the control is not using overhead memory. That is another thing to experiment with.
Then the user management view is probably going to be composed of two related views: a Roles control and a Users control. Each of those controls will have a list of their respective model data as well as a Detail view for selected items. So my next task will be to wire up the model to correctly display the system's roles and users as well as the command(s) for selecting an oject from the list and showing its properties in the details view.
In the Users control there will be commands for adding, editing and disabling users. (There is no deleting of created users.) This will give me a chance to do error handling and business rules regarding the users (like password strength and that the default Admin user cannot be disabled).
For each of the controls there are a couple view-related features like the refresh and filter commands. They may be interesting to experiment with in the MVVM framework, but aren't terribly important.
Finally, there is the relatively simple task of adding and removing users from roles, which will give me the opportunity to see how my two controls will communicate with each other.
So on to creating my application and creating the shell and bootstrapper.
Following the walk-throughs for Prism Guidance:
In Visual Studio 2010: New Project > Windows > WPF Application. I'm naming it AdjudicationPoC.
Change MainWindow.xaml to Shell.xaml. VS changes the code-behind name to Shell.xaml.cs, but need to change the actual class name and constructor and also go into App.xaml and remove the startupURI attribute. The Bootstrapper will handle what starts, and in fact we can just go in now to the App.xaml.cs code-behind and override the OnStartup method to create and run our Bootstrapper. Of course, now VS is going to bitch that we don't have a Bootstrapper class so let's add that to the project now too.
Now I'm going to make the executive decision to use Unity as our IoC container, so our Bootstrapper is going to inherit from UnityBootstrapper, and to do this we need to include the Microsoft Prism Libraries. Again following the walk-through in the Guidance I created a Libraries folder in my solution folder. I copied in the Prism libraries (I'm just leaving out the MEF libraries, since, at least for now, I won't be using them), and added the references to my project. Our development team usually keeps our 3rd party libraries outside the solution, so that will probably change, but good for now.
After adding those references I just need to override the CreateShell and InitializeShell methodsof the UnityBootstrapper to create an instance of the Shell, set it as the MainWindow of our App and show it. I'm sort of not crazy about the reference to the App here, since it would be nice to be able to unit test the bootstrapper (and, more importantly, automate that test) without it. It isn't doing much at the moment, plus I may see what MSTest can do for me in order to really test it. That's for tomorrow.
plus I may see what MSTest can do for me in order to really test it. That's for tomorrow.
Wednesday, December 7, 2011
Playing with Prism 4
We're at the end of this project I've been working on for some time now. As per usual, we kind of got into this fire drill situation of trying to get everything all wrapped up at the end. So things like trying to implement acceptance testing got pushed aside in favor of squashing all these bugs that popped up precisely because we didn't implement acceptance testing in the first place. That is all for another series of blog posts altogether I think.
Anyway, also as per usual we got to the end of this project and came to the realization that the architecture of the project was deficient to begin with. I don't mean to say that this just dawned on us. I mean I think we knew before that the architecture was deficient. I mean "realization" in the sense that the problem "manifested" (perhaps a better word) itself at the end. The core components of the application are a WPF client that interfaces with a web service as well as a windows service which handles data loading. The web service can interface with the windows service to report back to the client when loading occurs. Both services are WCF services, and we could probably improve on their architecture to an extent, but that was a bullet we bit about halfway through the project. At that time we made some significant changes to the service side, so while there are definitely some changes we could make, the architecture is ok.
On the client side though we ran into issues. The client-side architecture is a bastardization of one we used on a previous project. That project used the Composite Application Library and an MVP architecture. It was a big, complex application. We thought we could scale that down and cut out some things we wouldn't really need. It turned into sort of an ugly bastard child in every sense of the word.
So, after the fact (which is totally the way I LOVE to do things), I am looking at Prism 4, seeing how it improves I what we did with CAL and figuring out how we can use it for the second release of this project, which we'll probably start after the Holidays. So what follows in the next few episodes are my rambling thoughts as I experiment with Prism and WPF and reassembling pieces of the existing client into something that I don't want to throw out a window.
Anyway, also as per usual we got to the end of this project and came to the realization that the architecture of the project was deficient to begin with. I don't mean to say that this just dawned on us. I mean I think we knew before that the architecture was deficient. I mean "realization" in the sense that the problem "manifested" (perhaps a better word) itself at the end. The core components of the application are a WPF client that interfaces with a web service as well as a windows service which handles data loading. The web service can interface with the windows service to report back to the client when loading occurs. Both services are WCF services, and we could probably improve on their architecture to an extent, but that was a bullet we bit about halfway through the project. At that time we made some significant changes to the service side, so while there are definitely some changes we could make, the architecture is ok.
On the client side though we ran into issues. The client-side architecture is a bastardization of one we used on a previous project. That project used the Composite Application Library and an MVP architecture. It was a big, complex application. We thought we could scale that down and cut out some things we wouldn't really need. It turned into sort of an ugly bastard child in every sense of the word.
So, after the fact (which is totally the way I LOVE to do things), I am looking at Prism 4, seeing how it improves I what we did with CAL and figuring out how we can use it for the second release of this project, which we'll probably start after the Holidays. So what follows in the next few episodes are my rambling thoughts as I experiment with Prism and WPF and reassembling pieces of the existing client into something that I don't want to throw out a window.
Subscribe to:
Posts (Atom)