MVVM - Viewmodels in Datagrid rows? - wpf

i want to write a little programm to manage article.
the pgm should show a list of article in a datagrid.
the can be 500/1000 articles that must be displayed in the grid.
Should i use viewmodels in the datagrid rows like josh smith does in his example here http://msdn.microsoft.com/en-us/magazine/dd419663.aspx ?
i tested a little bit in joshs example.
so i took his customers.xml file and extended it to 800 customers.
-> the app took a little (more)time to start and closing it (if show click the "show all customer" button) will take a few seconds. So it should be a heavy load for the system using viewmodels ?
can someone explain me the advantage using viewmodels as datagrid rows instead of articles?
What is the better way ?
public ObservableCollection<ArticleViewModel> AllArticle { get; private set; }
or
public ObservableCollection<Article> AllArticleraw { get; private set; }

Whether or not to use ViewModels as your DataGrid Rows really depends on how much functionality each row must have.
If the grid is read-only, for display purposes only, and the underlying data will not change, then ViewModels would probably be overkill for a row.
However, if your user may interact with the row, perhaps edit values in a row, or if values in the row may change as a result of an external action, and you want those changes to reflect automatically in the grid, then you should consider ViewModels.
And keep in mind that a ViewModel is just a name for an object that serves a purpose - it can be as heavy or as light as you need it to be. For example, if you want your row to reflect changes in the grid immediately, it can be a simple POCO that has properties for each row column, and then implements INotifyPropertyChanged to notify the grid when one of those property values has changed.
Don't let heavy-weight implementations of ViewModels scare you away from the concepts of MVVM - implement only the features you need in each ViewModel.

Related

How to assign context and refresh it in Entity Framework?

I created a new entity object and bound it to controls in another window (edit window). After modifying and saving I assigned a new entity object into the one in the main window. The old entity object is bound into a datagrid, now I want the datagrid to display the data that I had modified and saved.
ObjectContext.Refresh Method (RefreshMode, Object) seems to be what I want but I don't know how to use it correctly.
In short :
I have a main window with datagrid displaying the whole data of the table. Users can pick one row and edit it in a edit window. After saving, the datagrid should display what has been modified.
Your best bet here is to use an ObservableCollection as your data source for the datagrid instead of the query.
And look at implementing INotifyPropertyChanged interface in your Customer class.
The ObservableCollection is initially populated by the database query. User changes are made to elements within the ObservableCollection and once complete you then just need to trigger transferring the changes to wherever you originally obtained your list of Customer objects
By doing this changes made both to the collection of Customers and to individual Customer objects (if present within the datagrid) will be automatically updated for you.
edit
I must admit that I'm a bit rushed to offer up any code at the moment, but here's a pretty good article that explains how to use ObservableCollections and classes that implement INotifyPropertyChanged. It also has code examples, which although in VB.NET should give you enough of an idea to get started.
In effect you separate your code into distinct layers UI (View), business logic (View Model) and data layer (Model where your entity framework resides).
You bnd your datagrid to the ObservableCollection type property in your Customers class and your edit csutomer window is bound to as instance of your Customer class.

How much coupling is appropriate between ViewModels in MVVM

I'm developing a fairly simple WPF application to display an object hierarchy plus detail of the selected object, with a UserControl wrapping a TreeView in the left pane (the tree control), and another UserControl wrapping a ListView/GridView on the right (the details control).
The tree control uses MVVM following this Josh Smith article reasonably closely, and has a number of ViewModel types all derived from the same base type, TreeViewModel. The main window is set up using a MainWindowViewModel as in this Josh Smith article and exposes the TreeViewModel used to populate the first generation of the tree control.
However, when I want to populate the details pane on the right, I have the problem that the SelectedItem of the tree control is derived from TreeViewModel when I need a completely different type of ViewModel for the details pane which will expand the object into a table of properties/values using reflection.
So, questions:
Is it appropriate for the MainWindowViewModel to expose the TreeViewModel for the tree control? I believe that the answer here is yes, but am open to suggestions to the contrary.
How should the selected item in the tree control be adapted to the right ViewModel type for the details pane? One option seems to be that the MainWindowViewModel tracks the selected item in the tree and does the adaption, exposing it as another property, but I'm not sure if there is a better solution.
I'm new to WPF and the MVVM pattern, so please excuse the fairly basic nature of the question. I've done a fair bit of reading around the background of the pattern, looked at some sample apps etc. but I can't quite find anything specific enough to make me confident of the answer. I also realise that MVVM may be overkill for an app this simple, but I'm using it partly as a learning exercise.
1.Is it appropriate for the MainWindowViewModel to expose the
TreeViewModel for the tree control?
I belive yes. The model should hide the look from teh logic FOR THE LOOK, but it can not hide thigns like logical structure.
2.How should the selected item in the tree control be adapted to the right
ViewModel type for the details pane?
One option seems to be that the
MainWindowViewModel tracks the
selected item in the tree and does the
adaption, exposing it as another
property, but I'm not sure if there is
a better solution.
IMHO not.
Working on the similar problem I came to the conclusion that
object Tag { get; set; }
property is inevitable :( except maybe for some rare situations (only 1 type of objects in the entire treeview).
However, when I want to populate the details pane on the right, I have the problem that the SelectedItem of the tree control is derived from TreeViewModel when I need a completely different type of ViewModel for the details pane which will expand the object into a table of properties/values using reflection.
If you're really, really concerned about this, you can build a higher-order view model class that exposes two different properties - one of type TreeViewModel and one of type DetailsViewModel. Then the main window's view model will expose the same object to both the tree control and the details control, but the logical structure of the two view types will be decoupled from one another.
Logically, the selected item in the tree control and the item that's appearing in the details control are the same thing. While the details control doesn't present information about the thing's parent/child relationships, and the tree control doesn't present information about the thing's name/value pairs, it's still the same thing. There's probably not really any need to be too concerned over the fact that a single object representing a thing exposes a property that only one view of that thing uses.

wpf - viewmodel with two bindable collections. Use datacontext of one collection to filter the other one

Long title, hope it makes sense. Can't seem to figure out how I would implement this. Or if my approach is even somewhat on track with best practices for this kinda stuff b/c i'm still working on mvvm and probably not using it correctly yet.
I have a simple viewmodel in an application i'm working on and it contains two properties which point to datamodel collections.
public ChuteGroupsModel Groups { get; set; }
public WaveStatusModel Waves { get; set; }
Each one of these datamodels contains all the data I need for a tabpage in my tabcontrol of my MainWindow. One tabpage is a grid of statistic data and the other page is a custom user control that visualizes a physical "working" area.
I decided today that I would like to display some of the statistic values from the grid (# of items, # remaining, etc) inside of the tooltips of my custom user controls. My two collections are only connected by an ID# field.
So, basically I need to figure out a way to filter/bind to my "Waves" collection according to the ID# property of the current element that is bound to "Groups".
The obvious easy answer here is to modify my sql view to include the additional fields which would make them immediately available for me to bind to in my application.
Since all of the data I wish to visualize already exists, I can't help but feel that changes to sql are a bit unnecessary and that some easy solution exists to help me gather these values out of my other collection.
Can anyone provide any suggestions of what I could attempt to do? If my question does not make sense I can try to re-state it with more code snippets and hopefully that will help.
Perhaps some more information about your ViewModel / View binding would be helpful. As given, if your ViewModel exposes properties of both Groups and Waves to your View, and the View containing the TabControl is bound to your ViewModel, I see no reason why controls on either TabPage couldn't be bound to properties sourced from either data model.
To put it another way, the ViewModel can abstract away the separate data-model collections from the View, building, for example, its own collection of objects which expose the properties of both a ChuteGroup and its associated WaveStatus. The View can then be bound to that collection, and access the properties of both objects.

How to pass EventArgument information from view to view model in WPF?

I have ListView control in my application which is binded to the collection of CustomObject List<CustomObject>. The CustomObject has seperate view. This ListView has seperate view model.
The collection List _customobject is containted in the ListView ViewModel class.
My Query:
I want to invoke a view that show properties of custom object, when user double click on any row of ListView. The ListView double click command is binded to the ListViewDoublClick Command in the view model. The CustomObject is in the event argument of listview double click command. To acheive this I have to pass the custom object ( or an unique id property of custom object through which I can retrieve the custom object from the collection) as command parameter.
Please suggest me the solution!!
The easiest way to do this is to add a double click event handler to the list. Remember: MVVM does not mean no code in the view! It means that the view only handles view concerns. You can make a really good argument that the EventArgs are only meaningful to the view and if you want to pass it to the ViewModel you should only pass the relevant information.
If you have to do something like extracting data from an EventArgs to pass it to the ViewModel, that is acceptable and proper... and better than passing the EventArgs down into the ViewModel, IMHO.
(I'm sure I'll get some disagreement on this point, but dealing with UI interaction is a View concern and if the alternative is writing a behavior or using a framework to get a single control working on a single page, remember: YAGNI and Patterns are not Religion.)
Several of the MVVM frameworks allow you to do this (although there is a lot of discussion about if it's a good idea or not). Inparticular, the MVVM Light Toolkit added this a little while ago to support drag and drop (if I remember the blog post correctly).
If you're not using a MVVM framework, I have wound up writing a behavior to allow me to do this if I was going to do the same thing in multiple places. In this case, I usually extract the information I care about from the EventArgs (i.e. you probably don't really want the full event args, but you probably care which item was clicked and maybe a few other bits of data).

Is it just me, or is WPF a mess of databinding and custom IValueConverters?

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.

Resources