I was just curious if this is a good or bad practice or what the most preferred way of doing this is.
The practice I am referring to is that as I am a newb to WPF as I'm going along I have found it handy and useful to put strings, xdocuments, and domain objects into the Application.Resources in the app.xaml when their data is to be needed across the application, and for the simplicity of the static resource binding by x:key.
Good? Bad? Why? What should I do instead? Please no links to large MVVM tutorials and such, just looking for a concise answer regarding this specific practice, if MVVM has an answer for it I'm glad to hear what it is, I just don't want to read a 6 page tutorial or blog to find out..
I implement an application view model (AVM) object. Anything that needs to get exposed to the application views globally gets implemented as a property in the application view model so that I can get to it via binding. This makes for a nice consistent access method, gets me testability, implements property-change notification, gives me a place to put application-wide commands, all the stuff that you'd expect from using a view model.
The data context for every top-level window is set to the instance of the application view model. So I don't need to mess around with the resource dictionary or remember key values at all. That may sound a little weird at first - why would two windows use the same view model? - but if you want to put the same File/Exit command on every window that the application spawns, this actually makes logical sense. In such a case, the window's data context is set to the AVM, and then it contains a panel whose data context is set to a property on the AVM that's the actual context for that window. As long as you give your window element a name, binding to objects on the AVM is trivial - {Binding ElementName=TheWindow, Path=DataContext.TheProperty} - or you could expose the AVM as a property of the child view models.
The AVM pattern is subject to the same pitfalls as any one-object-to-rule-them pattern - e.g. creating a shambling beast with 200 unrelated properties. The solution's the same: aggregate those properties into service classes.
I generally don't put anything in the resource dictionary that doesn't get created in XAML. I can think of lots of valid exceptions to this general rule, but they haven't occurred in my programs yet.
Putting things in App.xaml could be a problem when:
You start branching your application into separate assemblies as the assemblies cannot 'see' app.xaml design-time - you can only find bugs run-time.
You have a magic string for pointing at your resource which is easy to misspell - or worse yet, duplicate by accident.
It is hard later to find the places any given resource is used and whether it can be safely changed ('What was it UpdateFrequency was for...')
You want it to be configurable - the AppSettings part of the app.config file is much better for these kinds of settings.
It's essentially the same problems as using global static variables for settings.
EDIT: Things, I prefer to have in App.Xaml is:
Global Styles and DataTemplates - in other words - things used for visual presentation that is there to override 'standard' settings - so usually they have no x:Key tag but rather a TargetType="{x:Type SomeType}"
Hope this helps!
This does make sense for ones shared across the application - "don't repeat yourself". I would also recommend having a project-specific resource that merges the application resources. The controls should reference that rather than the application resources.
This makes the controls in the project more self-contained.
I'd also recommend breaking resources into logical groups and merging them rather than having "one big bucket".
Related
I'm working on a WPF project using the MVVM pattern and I was wondering if I can improve the internal structure of my ViewModel by abstracting its exposed properties into separate classes.
It's common practice for VMs to contain lots of properties laying around in the same class: Some are used to retrieved user inputs, some are used to expose commands, others to expose the models, and probably some other properties for the view model's own business logic. Not to mention that these properties often have set and get bodies that adds some bulk to the package. This can quickly become messy inside a VM class and finding one's way there can become challenging.
As a way to solve this issue, I am exploring with my team the idea of grouping properties inside my VM into different categories. As a first approach, I chose to group them this way:
ViewData, UserInputs and Commands, each one represented by its own class. Then I referenced them as properties inside my VM class.
My intention is that these classes will only act as placeholders to free up the bloat in my VM and keep it clean and focused only on interaction logic for handling user events.
It's a simple refactoring, but I get the following pros:
Cleaner and readable VM.
Easier binding from the XAML because you know what the entry point is/should be.
Let me elaborate on the latter one: If I want to bind a text box to a property of my VM, I know the binding expression should start with Userinput.MyVMProperty. If I need to show a value from my VM, I know my binding's entry point is going to be ViewData.MyOtherVMProperty. Binding intellisense will also become better because when you know your entry point, the
suggestion list would be smaller and more focused. This also works the other way around: when reading through your XAML controls, any binding that starts with UserInput necessarily means it's a a control that should send data back to the VM.
The only cons I can find is that this will require creating extra classes for each VM, but I believe it's a fair price to pay for the benefits you get.
Take note that the grouping I suggested may not be the best, but I don't mind any other grouping as long as it solves the problem with bulky VMs.
So, has any one ever tried a similar pattern? Do you think this is a good idea/practice? What other good practices I can use to improve my VMs?
Bonus question: One developer in my team who seemed to agree with this idea, suggested to go the extra mile and consider the grouped classes as VM dependencies and that they need to be injected inside the VM. What do you think about this?
So for every ViewModel you need to create own inner classes for every group. You cannot use Interfaces because ViewModels have different properties and commands
Then did you considered that every "groupclass" must to "know" about other groups for ViewModel will work properly.
In my opinion Class should be solid logical structure with minimal outside dependency.
Based on the pros you trying to achieve I can suggest another approach without changing structure of the ViewModel classes
Readability can be achieved partly by #regions.
Or use Partial class for separating different groups in the different files,
while keeping them inside one logical structure
Intellisense can be improved by naming conveniences - using prefix based on group property belong to. For example UserInputMyName, ViewDataFullName or CommandDelete
I have a Silverlight application that consists of many pages that uses Navigation Framework. What is the ideal place to store data that should be accessed across all pages (XAMLs) and throughout
the lifetime of the application.
EDIT: Forgot to mention that I am currently doing it as a static class
Static members are generally a bad idea. You have no control over lifespan or ability to easily substitute another set of data (and don't get me started on the inability to do proper unit testing). You want to use some type of shared View Model/Data model.
If you are not going the whole PRISM route (we always use PRISM now for Silverlight and WPF), or Unity, or even just MVVM, then use simple singleton accessors on your data object.
There are lots of discussions over the best patterns for C# singletons, but you can learn a lot here http://www.yoda.arachsys.com/csharp/singleton.html
Hope this helps.
I like to create a class called Session, with a static property like this public static Session Default {get {return App.Current.Resources["Session"] as Session;}}, then create a new instance of it in app.xaml like this <classes:Session x:Name="Session"/>, now you can access it in code behind with Session.Default... and you can bind to it with Source binding and it will always be the same instance. I have expanded this pattern to a more complex and flexible pattern with base classes etc but that should suffice for your purposes. I wrote this code in this web window, it might not compile, if you need more help just let me know
We've been using the MVP pattern and Winforms with a fair amount of success. However, a question always pops-up about MVP:
What is a good granularity for presenters?
What I mean by that is: With Winforms, a fine-granularity usually works quite well for user controls. That way, it's easy to reuse user controls and use them as building blocks while designing more complex GUIs. However, having the same (fine-)granularity with presenters seems to be a problem.
On one hand, having coarse-grained presenters hinders the ability to use "plug-in" controls and it sorts of violate the DRY principle: Multiple presenters often need to implement the same logic (populate a list of customers, for instance), which is used by multiple, more complex, controls.
On the other hand, fine-grained presenters seem to limit the ability to reuse controls in different situations. For instance, an editing view might sometimes need to save the customer right away; sometimes it needs to link it to something else; sometimes is just needs to validate it; and so on. It often depends on the more complex control. But there's also a fair amount of shared behaviour.
Note that, in both cases, 1-presenter-1-view is achievable. What is considered "1-view" changes.
What is usually considered best-practices for presenter granularity using MVP and Winforms?
Fine-grained presenters and customizable behaviour through options or something of that nature?
Coarse-grained presenters and low presenter reusability?
Something else?
Disclaimer: We mainly use Supervising Controller but I think it also applies to Passive View. Sorry for the long question, too.
We use MVP at all of our clients and this is definitely a conversation that comes up in more than one occasion. How clean should our code behind classes and presenters be? Having said that, we have chosen to use the coarse-grained presenter approach. Basically, every form would have its own presenter and would only get and set properties of any of the controls on a particular form using its view. Populating controls-a call to a db to populate a combobox for example-is located in a public service class. Any validation of user inputted data is located in a BO class which can be reused by any and/or all of the presenters. I hope this helps.
In my CAD-CAM system my presenters don't use user controls. User controls reside in the view which reside in a EXE assembly that implement the view interfaces the presenter use.
If want to display a list of customers I hand it off to the view which has a DisplayCustomerList and it uses whatever combination of user controls it needs to display the customer list. If multiple views show the customer list in the same way then in the ExE/View assembly they share a user control or class for doing that. That class doesn't go outside of that assembly.
Our software is adapted to run many different types of metal cutting machine. So we place a lot of emphasis on being able to rip off the UI and replace it with a completely different UI (corresponding to a different machine). All of these UIs reference the same set of core assemblies.
The hierarchy looks like this
View EXE
Presenter Implementation
Command Assembly - commands are executed by the presenter that modify the model
Presenter Interfaces
Model Assemblies
Off to the side are loadable assemblies that define dynamic content like what file types can be loaded, reports, cutting device drivers, etc. These implement various interfaces found in the model assemblies
One thing I do is that I don't impelment a view presenter for every dialog. If the dialog is tightly bound with a command then it is defined, created, and used along side the command class. Occasionally a group of related commands will share a dialog (File handling for example).
The essential question I ask when using MVP is "What happens if want to completely replace the forms with something else?". The answers to that question will identify where you are too dependent on a particular user control or form engine.
The biggest problem (and one that I haven't got a good answer for) of my setup is that current IDEs and langauges make it very easy to tie user controls to database records. It is so productive compared any other setup it tends to dominate the design. I haven't had to deal with the issue much in my CAD-CAM application so I don't have any answer other than passing the dataset to the view and let it handle it. This site has some patterns that may be of use in this situation.
I have developed some MVVM based WPF code and am in need of some minor refactoring but prior to doing that I need to decide the best architecture.
I originally started with an application that could present several similar (but separate) representations of my data. Let's call it RecordsViewModel which had a corresponding RecordsView. As time went on, I introduced a SettingsViewModel which was passed into the constructor of the RecordsViewModel and published visibly (allowing RecordsView to use it). The SettingsViewModel is registered to so that changes are reflected in all of my views.
Now I want to split RecordsView a little because it now contains two distinct views.
The problem I have is:
the new (RecordsMainView and RecordsAlternativeView) both want to see Settings.
unlike the earlier RecordsView which is programmatically instantiated, these new views are instantiated from Xaml (default constructor).
So my options seem to be:
Walk the Tree Model upwards to find a parent with a Settings
Make Settings a DependencyProperty on the controls and make the Xaml join the Property to the instance.
Make SettingsViewModel a Singleton.
Any other, better, options? Which would you consider best?
I would turn your settings logic into a service (ISettingsService) and use service locator or dependency injection to get at that service from whichever view models need it.
Services are great for managing shared state, and service locator / DI makes it very easy for your VMs to get a reference to the service. Storing shared state in a VM is a bit hacky and - as you've found - doesn't really scale. A good rule of thumb might be to ask yourself whether the state in the VM exists only to support the corresponding view, or whether other components will need access to that state. If the latter, move it into a service.
I'm still new with C#, and I'm working on a project where we also use WPF, and the WPF DataGrid Toolkit (See at CodePlex), which hasn't yet been released into the framework. Due to the nature of the project, it's 100% sure we will be altering some controls of the assembly later.
My co-workers have decided to redefine every control from the datagrid within a namespace of our project, and ihnerit the specific control of the assembly namespace.
So instead of using:
clr-namespace:Microsoft.Windows.Controls.Primitives;assembly=WPFToolkit
clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit
We'll be using our own xxx.Controls and xxx.Controls.Primitives Namespaces.
This way, it would be pretty easy to alter the ihnerited controls.
Somehow, I got a bad feeling about this solution, but I'm still inexperienced and cannot tell if such an approach is legitimate or not, or if there is another good solution to our requirements (altering the controls later without changing too much code in multiple files).
It would be nice if you express your opinion to this approach.
What kind of alterations are you talking about? It seems like a waste of time to pre-emptively derive from each of the classes before you know what you'll actually need to change.
When you do need to change something, it shouldn't be too hard to create the derived class at that point, and fix up any references - which may only be for some instances rather than all of them. Yes, it may mean check-ins involving quite a few files - but if you're using a sensible source control system it will be an atomic change, and it will be obvious why it's changing.
With your current approach, there's no immediate "these are the controls we've had to change" - if you do it in a "just-in-time" manner, you'll be able to tell just by looking at what derived controls you've actually had to create.
I agree with you. The alterations, or better said, the changes, can be of any kind. Behavior and etc. And the changes should be make just in time.
Unfortunately, that is not my decision. Some stubborns are at work :)
But what is interesting me is if a complete different approach to the whole idea exists?
Say, I've got a DataGrid, the project evolves, and now, I've got to do some drastic changes in the validation behavior of dataGrid rows.
This could also apply to a lot of controls.
The problem with our project is, we have a kind of complex data access layer, which not only provides data, but also actually controls it. This means data isn't read,modified, deleted or appended without including some logic provided by the data access layer.
For an example, the datagrid doesn't directly delete rows, but instead, we overwrite the delete behaviour and aks the data access layer to delete it. With binding, this works pretty good for now.
This kind of scenario will apply to a lot of other things in the future, regarding CRUD operations, validation and etc.