I am learning wpf. I am trying to utilize tdd practices with wpf. I have the following code in one of my viewmodels that saves data from a control into an xml file -
void saveStr()
{
string source = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + #"\Data\Connections.xml";
DataGrid dg = FindChildViewItems.FindChild<DataGrid>(Application.Current.MainWindow, "MyDataGrid");
List<XmlSettings> list = new List<XmlSettings>();
foreach (var i in dg.Items)
{
if(i.GetType().ToString() == "MyProject.Configuration.XmlSettings")
{
list.Add((XmlSettings)i);
}
}
saveXml.Save(source, list);
}
The FindChildViewItems simply uses the visualtreehelper and dependency objects to find child items from the view (adapted from a post here).
My question is whether that adheres to tdd patterns since it has a dependency on the view when I am looking back to the view to get the contents of that particular control.
Is there another way to get the information from the datagrid on the view so that the contained data could be saved to an xml file.
I hope that makes sense......
Thanks for any thoughts.
Well, it looks like you're breaking several patterns here. It's definitely going to be very difficult to test.
Perhaps I can help you smooth out your structure a bit to make it more testable.
First, your viewmodel should not be saving state to a file! Your viewmodel should update the model whenever the user changes data in one of the datagrids, and nothing else. Use two-way databinding to allow your viewmodel to know when the view changes.
Persisting state to a file should be done in a different part of the program, possibly by a standalone command object, possibly in an event (alot of where this should occur depends on your program structure, and I can only guess at that). Regardless of where it occurs, it should be outside both your viewmodel and your model, and it should use your model to obtain the data it writes to a file.
After some minor tweaks to your method to account for this, it should be totally testable. Give it a stubbed model object (preferrably a class that only has user config settings) and let it go to town with your fake data.
Testing writing the file then becomes your biggest issue. Difficult to automate.
But testable.
Ideally, if you would like to do proper TDD (Test Driven Development), you should try to use MVVM Design Pattern. It separates View from the ViewModel, thus making the ViewModel and Model easily testable.
if you have used MVVM in the above example, your Model would have save() method in it and then you would call it from VM. That way you can easily test your Model to make it saves.
And later on you can also test your VM, to make sure when you call SaveCommand it calls your Model's method. let me know if you need further info (google for MVVM if you havent heard about it before)
Related
My Desktop WPF application has a repository (of type Person) which resides in the Model layer, and is called by a ViewModel which has a PersonList property which is databound to a DataGrid.
When I open my Application, the list is shown by default. During initialization, the following code applies:
public class PersonScreenViewModel : ViewModelBase
{
PersonRepository _person_repository;
public ObservableCollection<Person> PersonList { get; set; }
public PersonScreenViewModel() {
_repositorio_pacientes = new RepositorioPacientes();
PersonList = new ObservableCollection<Person>(_person_repository.GetAll());
}
// ... ///
}
My doubts are based on some difficulty to understand how to implement "Save / Update" method(s).
Every text about the Repository pattern tells that "the repository should behave like a collection of [ entities | domain objects ]". So, the most logical thing would be to databind the repository itself to the DataGrid. That could be done if I created a class which inherit from ObservableCollection and implements repository logic. Currently, what I do is take a copy of the repository items, using _repo.GetAll(), and work in that copy, having to commit back after my changes are done.
Specifically, my workflow involves selecting a row in the DataGrid, changing some properties of the selected object, and commiting these changes, expecting that the same object is persisted with the new property values.
Usually, if you take an object in a collection and modify it, you don't need to "update" anything, since you already changed the object itself.
The question is: "How can I data bind my view to the repository itself? Should the repo inherit from ObservableCollection? How is it supposed to be done? Is some part of my reasoning flawed?"
It is important to say that my application is not data-oriented, the Person class is very basic (POCO marked as [Serializable], with a few properties), and my repository uses plain XML serialization and the filesystem structure.
Thanks for reading!
"Every text about the Repository pattern tells that "the repository should behave like a collection of [ entities | domain objects ".
What you originally have is sort of correct. First of all ObservableCollection works perfectly with the View because every add/update/delete will automatically propagate back to the user interface. If you implemented it with repository, then you would have to go call the database reload the control bound to your repository
"How can I data bind my view to the repository itself? Should the repo
inherit from ObservableCollection? How is it supposed to be done? Is
some part of my reasoning flawed?"
You don't want to data bind the Repository to the DataGrid itself, because you lose caching and every time the user loads the user control you always have a trip back to your database.
You don't want to inherit a repository to an ObservableCollection, ObservableCollection has more overhead vs simple IEnumerable given you already database returned you a collection already.
You always don't want ObservableCollection as your collection for your data because it is expensive. A simple enumerable of data is enough depending on your scenario (Read-only data).
In my personal opinion, what you are currently doing is correct... it is generally good practice to have some separation between the various layers of your application; Models, View Models, Views and DataAccess (sometimes combined into Models). Having said that, it really depends on your application... it might not be worth doing this on small applications as it adds a lot of code and time to set up and maintain.
However, the main reasons for providing this separation (called separation of concerns) is to enable unit tests to be able to test the individual layers without concerning the other layers. For example, if we wanted to write unit tests for our view models, we wouldn't want to test their functionality on the actual data objects in the database. If we have this separation (through the use of interfaces) then we can simply mock up data objects to use during these tests.
Another reason, although less common in practice, is to enable whole layers to be 'swapped out' without affecting the code in the other layers. Examples of this would include changing the database used in the application, or maybe changing the views from a desktop application into web pages in a web application. If we have separate layers, then these changes won't affect the other layers.
So to answer your question directly, I wouldn't bind your views to the repositories at all... keep your current separation. After all, how long does it take to copy a collection sourced from the database into a view collection property?
UPDATE >>>
I'm not sure that I fully understand the question in your comment. I'm guessing that you are binding your PersonList property in your view model to the DataGrid.ItemsSource property to display the data. Any changes made in the DataGrid should affect the items in your PersonList. If you were to add a 'Save' Button, then you could update the database in that click or command handler.
If you were enquiring how to find out which elements had been changed, there are several methods for accomplishing this. There is a good tip in the How to get only modified Items from WPF Data Grid post here, but I prefer to use a duplicate collection and just compare them to find the changed elements (you'd need to implement the Equals method for this to work).
Please let me know if that does not answer your question.
In my WPF MVVM application my model is a complex tree of Model objects wich constantly changes at runtime. Model instances come and go at runtime, change their position within the tree and of course change their many properties. My View is almost a one-to-one visual representation of that tree. Every Model instance is in 80% of the cases also a node in the tree.
My question is now how I would design the ViewModel around this? My problem is that there are quite a lot of different Model types with each quite a lot of properties. If I understood MVVM corretcly the view should not communicate with the Model directly so this would mean that I would have to create a ViewModel type for each Model type and have to rewrap each property of the Model type in the ViewModel.
Also the ViewModel would need to "bind" to the propertychanges of the Model to pass it along to the view (using wpf datatbinding). I would need some factory that creates and introduces a ViewModel instance for each Model that appears anew and I would habe to dispose each ViewModel instance when the corresponding Model disappears. I end up keeping track of all instances I created. It is unbelievable how much bloat code is generated dues to this double wrapping.
Is this really a good approach? Each entity and each property more ore less exists twice and I have a lot of extra code keeping Model and View in sync. How do you handle this? Is there a more clever way to solve this?
Does anyone have a reference/sample implementation for this that does it better than I do?
I think you may run into trap of paradigm if you follow this path. MVVM is nothing more than a pattern, which simplifies development in WPF world. If it doesn't - don't use it or revise your approach. I wouldn't spend 80% of my time just to check the "Using MVVM" field.
Now back to your question. Correct me if I'm wrong, but it sounds like you are looking at MVVM from opposite direction: you don't need Model to ViewModel one-to-one correspondence. Usually you create ViewModels based on your View first, and only then on a Model.
Generally you look on a screen mockup from graphic designers, and create corresponding ViewModel, which takes all necessary fields from the Model, wraps/modify/format/combine them to make View development as easy as possible.
You said that your View is almost one-to-one visual representation of the Model. In this case it may have sense to create a very simple ViewModel which exposes root object of your model-tree, and let View consume model directly via that property. Then if you need some View customizations or commands processing you can delegate that to ViewModel.
Sorry for very vague answer. Maybe if you ask more specific question we could dispel the confusion :)...
Seriously, it seems like every time I want to make my UI elements talk to each other, I end up coding a new, custom, IValueConverter :(. Someone tell me that I'm doing it wrong, please!
Examples:
I wanted a button to be enabled only if my textbox contained a valid URI. Great, time to code up a UriIsValidConverter!
Oh oops, I also wanted to disable it while I'm processing something. I guess now I need to code up a UriIsValidAndBoolIsFalseMultiConverter!
I want to display a list of files in a certain directory (specified by a textbox) inside a listbox. I guess I need a DirectoryPathToFileList converter!
Oh hey, I want icons for each of those files in the listview. Time for a FileInfoToBitmap converter!
I want my status to be red if my status-string contains "Error", and green otherwise. Yay, I get to code up a StatusStringToSolidColorBrushConverter!
I'm really thinking this isn't that much better than the old Windows Forms method of just wiring up everything manually using TextChanged events (or whatever). Which I guess is still an option. Is that what people actually do, perhaps, and I'm trying too hard to make everything fit into the databinding paradigm?
So yeah, please tell me if this is really how WPF coding is---or if I'm doing it wrong, and if so, what I should be doing.
Your approach is perfectly valid (though I would use a multibinding for the second example, rather than a such a specialised converter), though by placing all your logic into the XAML you are producing very high coupling between the way the application looks and the way that it behaves, because of this you may want to look into the MVVM pattern to separate those things out.
Under the MVVM pattern your XAML (the view) just contains very simple data bindings into a ViewModel which handles all the logic and updates the view through the INotifyPropertyChanged interface. The code for your third example may look something like:
public class DirectoryManagerViewModel : INotifyPropertyChanged
{
private string _directory;
public string Directory
{
get { reutrn _directory; }
set
{
if (_directory != value)
{
_directory = value;
OnPropertyChanged("Directory");
if (IsValidDirectory(value))
{
PopulateFiles();
}
}
}
}
public ObservableCollection<FileViewModel> Files { get; private set; }
private bool IsValidDirectory(string directory)
{
//return if the directory exists etc.
}
private bool PopulateFiles()
{
//Populate Files with files in directory
}
}
Where FileViewModel is another view model which contains the name and the icon for a file.
The advantage of this approach is that the ViewModels can be reused with other views and other technologies such as ASP.NET or Winforms so you are not locked into the WPF stack. (alos if you work in an environment where there are designers responsible for the look and developers responsible for the behaviour, this helps define those boundaries)
At the end of the day though this logic does need to go somewhere and while there are better and worse ways to architect your application you are still going to be writing code that takes a string and converts it into a series of filenames and icons somewhere.
First, you might want to start by reading about the Model-View-ViewModel pattern (MVVM). Josh Smith had a fantastic article in MSDN Magazine recently. MVVM and WPF go perfectly together. Done right, you won't need IValueConverters so much. The way that you are going about it now is causing a very tight coupling between your visualization and your application actions. MVVM is designed to decouple these elements.
In this context, your view model will track state for you. Your button will be enabled if the CanExecute method on a certain ICommand in your view model returns true. This same concept can handle disabling the button when processing something.
You want to display a list of files in a certain directory that is specified inside a listbox? Have a DirectoryViewModel view model that will handle providing the list of files to the view by binding to the view model. The display of the files can be specified with a DataTemplate specified in XAML with no code behind. This same concept can handle providing the icons to the view whose display can be specified in the template.
You want your status to be red if a status message contains "Error" and green otherwise? Let a view model handle determining the state and let the view bind to that state and now you only need an IStateConverter to convert the state to red or green appropriately (this is one of many ways to handle this problem in the MVVM context).
Get in the habit of keep data and state separate from your view and your applications will be loosely coupled, easier to design and maintain, and easier to test.
Don't know if you are wrong, just making it a lot harder than it has to be!
I use MVVM, so where you are writing customer converters, I provide a bindable property on the view model that tells the view what to do. For example:
To display a list of files, I provide a collection that contains that list.
If I want icons the object in that collection has a icon property
If I want a status to be red or green I provide a StatusColorbrush property.
By moving this logic into the view model, I get:
much simpler Xaml.
can test my view logic without the view.
This approach uses one of the strong points of WPF, it's binding capabilities.
Problem Statement
I'm writing a very basic WPF application to alter the contents of a configuration file. The data format is an XML file with a schema. I want to use it as a learning project for MVVM, so I have duly divided the code into
Model: C# classes auto-generated from xsd.exe
View-Model: View-friendly representation of the Model.
View: Xaml and empty code behind
I understand how the View-Model can make View-binding a breeze. However, doesn't that leave the View-Model <-> Model semantics very awkward? Xsd.exe generates C# classes with arrays for multiple XML elements. However, at the V-VM level you need Observable Collections.
Questions:
Does this really mean I have to keep two completely different collection types representing the same data in coherence?
What are the best practices for maintaining coherence between the Model and the View-Model?
I'm not a big expert, but I think that is the case yes. The general idea is indeed to propagate change between the view and the viewModel via Binding, and then between the ViewModel and the Model via events (in the Model -> ViewModel direction) or dependency (in the other direction).
I don't know how standard that is, but my understanding of MVVM is that the ViewModel should hold a reference to the model so that when the user modifies the view, the ViewModel should call the appropriate code on the model. The other way round, the Model should raise events when modified, and the ViewModel should update itself accordingly (the ViewModel being an observer to the model).
#Does this really mean I have to keep two completely different collection types representing the same data in coherence?
I think yes. It's pretty boring, but it works quite well. Hopefully, in the future we will have also a code generator to create the ViewModel part.
Karl is working on that: http://karlshifflett.wordpress.com/mvvm/
You need clearly ObservableCollections at the viewmodel so, yes, you will need two
completely different collection types in the model and in the viewmodel.
I have done an article about doing undo / redo in MVVM where you can find a possible solution to this. It uses what I call the MirrorCollection: an ObservableCollection derived class witch automatically obtains his items from a List (the list of the model).
I think it is an interesting solution, you can find the articles here
Part 1: Using the Viewmodel pattern to provide Undo / Redo in WPF
Part 2: Viewmodelling lists (here is the MirrorCollection definition)
Expose Events or delegates in Model and hook to the same in ViewModel, when ever values in the model changes notify to viewmodel via event or delegates and from Viewmodle you can update the UI.
If you want to update it from view model to model as simple as that just call some method pass the new values
I have an MVVM application. In one of the ViewModels is the 'FindFilesCommand' which populates an ObservableCollection. I then implement a 'RemoveFilesCommand' in the same ViewModel. This command then brings up a window to get some more user input.
Where/what is the best way to do this whilst keeping with the MVVM paradigm? Somehow
doing:
new WhateverWindow( ).Show( )
in the ViewModel seems wrong.
Cheers,
Steve
I personally look at this scenario as one where the main window view model wants to surface a task for the end user to complete.
It should be responsible for creating the task, and initializing it. The view should be responsible for creating and showing the child window, and using the task as the newly instantiated window's view model.
The task can be canceled or committed. It raises a notification when it is completed.
The window uses the notification to close itself. The parent view model uses the notification to do additional work once the task has committed if there is followup work.
I believe this is as close to the natural/intuitive thing people do with their code-behind approach, but refactored to split the UI-independent concerns into a view model, without introducing additional conceptual overhead such as services etc.
I have an implementation of this for Silverlight. See http://www.nikhilk.net/ViewModel-Dialogs-Task-Pattern.aspx for more details... I'd love to hear comments/further suggestions on this.
In the Southridge realty example of Jaime Rodriguez and Karl Shifflet, they are creating the window in the viewmodel, more specifically in the execute part of a bound command:
protected void OnShowDetails ( object param )
{
// DetailsWindow window = new DetailsWindow();
ListingDetailsWindow window = new ListingDetailsWindow();
window.DataContext = new ListingDetailsViewModel ( param as Listing, this.CurrentProfile ) ;
ViewManager.Current.ShowWindow(window, true);
}
Here is the link:
http://blogs.msdn.com/jaimer/archive/2009/02/10/m-v-vm-training-day-sample-application-and-decks.aspx
I guess thats not of a big problem. After all, the Viewmodel acts as the 'glue' between the view and the business layer/data layer, so imho it's normal to be coupled to the View (UI)...
Onyx (http://www.codeplex.com/wpfonyx) will provide a fairly nice solution for this. As an example, look at the ICommonDialogProvider service, which can be used from a ViewModel like this:
ICommonFileDialogProvider provider = this.View.GetService<ICommonDialogProvider>();
IOpenFileDialog openDialog = provider.CreateOpenFileDialog();
// configure the IOpenFileDialog here... removed for brevity
openDialog.ShowDialog();
This is very similar to using the concrete OpenFileDialog, but is fully testable. The amount of decoupling you really need would be an implementation detail for you. For instance, in your case you may want a service that entirely hides the fact that you are using a dialog. Something along the lines of:
public interface IRemoveFiles
{
string[] GetFilesToRemove();
}
IRemoveFiles removeFiles = this.View.GetService<IRemoveFiles>();
string[] files = removeFiles.GetFilesToRemove();
You then have to ensure the View has an implementation for the IRemoveFiles service, for which there's several options available to you.
Onyx isn't ready for release yet, but the code is fully working and usable at the very least as a reference point. I hope to release stabilize the V1 interface very shortly, and will release as soon as we have decent documentation and samples.
I have run into this issue with MVVM as well. My first thought is to try to find a way to not use the dialog. Using WPF it is a lot easier to come up with a slicker way to do things than with a dialog.
When that is not possible, the best option seems to be to have the ViewModel call a Shared class to get the info from the user. The ViewModel should be completely unaware that a dialog is being shown.
So, as a simple example, if you needed the user to confirm a deletion, the ViewModel could call DialogHelper.ConfirmDeletion(), which would return a boolean of whether the user said yes or no. The actual showing of the dialog would be done in the Helper class.
For more advanced dialogs, returning lots of data, the helper method should return an object with all the info from the dialog in it.
I agree it is not the smoothest fit with the rest of MVVM, but I haven't found any better examples yet.
I'd have to say, Services are the way to go here.
The service interface provides a way of returning the data. Then the actual implementation of that service can show a dialog or whatever to get the information needed in the interface.
That way to test this you can mock the service interface in your tests, and the ViewModel is none the wiser. As far as the ViewModel is concerned, it asked a service for some information and it received what it needed.
What we are doing is somethng like that, what is described here:
http://www.codeproject.com/KB/WPF/DialogBehavior.aspx?msg=3439968#xx3439968xx
The ViewModel has a property that is called ConfirmDeletionViewModel. As soon as I set the Property the Behavior opens the dialog (modal or not) and uses the ConfirmDeletionViewModel. In addition I am passing a delegate that is executed when the user wants to close the dialog. This is basically a delegate that sets the ConfirmDeletionViewModel property to null.
For Dialogs of this sort. I define it as a nested class of the FindFilesCommand. If the basic dialog used among many commands I define it in a module accessible to those commands and have the command configure the dialog accordingly.
The command objects are enough to show how the dialog is interacting with the rest of the software. In my own software the Command objects reside in their own libraries so dialog are hidden from the rest of the system.
To do anything fancier is overkill in my opinion. In addition trying to keep it at the highest level often involving creating a lot of extra interfaces and registration methods. It is a lot of coding for little gain.
Like with any framework slavish devotion will lead you down some strange alleyways. You need to use judgment to see if there are other techniques to use when you get a bad code smell. Again in my opinion dialogs should be tightly bound and defined next to the command that use them. That way five years later I can come back to that section of the code and see everything that command is dealing with.
Again in the few instances that a dialog is useful to multiple commands I define it in a module common to all of them. However in my software maybe 1 out of 20 dialogs is like this. The main exception being the file open/save dialog. If a dialog is used by dozens of commands then I would go the full route of defining a interface, creating a form to implement that interface and registering that form.
If Localization for international use is important to your application you will need to make sure you account for that with this scheme as all the forms are not in one module.