0

I have been reading about MVVM on WPF. As long as I understand right, in MVVM I should divide the Model (data to display) from the way to show it (the View) using ModelView to link both, right?

So what I want to do is use a DataSet as Model, with n number of fields coming from a database. The field names, type and order are variable (is a Select from a SQL Server View).

The view will be a WPF form with a Datagrid.

So I should build my modelview in a way that iterates on each field from the DataSet and depending on Field Type format the data to show it later on the grid.

It is possible to do this whith MVVM Templante on WPF?

Thanks in advance

UPDATE

I will try to clarify my scenario and what i try to do, based on LordTakkera comments. I'm bulding a Client-Server Layered application using .NET technologies. Client and server will be in different machines, comunicating with WCF. A few different clients will use this software, so suppose this scenario: Client 1, 2 and 3 need a sales report showed on a grid.

Client 1 need: Sales Date, Client Name and sale import.

Client 2 need: Sales Date, Vendor name and sales import.

Client 3 wants to add to his Client table a numeric field that represent espected sales per client and whants to show it in sales report.

If i use Strong data Types, i need one binary for each client, im i rigth? What i want is to use the same binaries for client 1, 2 and 3 changing the output from sales report based on database data.

Why? many reasons:

1) Eliminate Bugs: If i find a bug in some class i can correct it, recompile and give the corrected binary to all my clients.

2) Scalability: If i add some function to the system wich was asked by client 1, i can give that function to all my clients.

3) Flexibility: i can change the behavior of the software for each client with the same binary.

I understand the advantage of strong type, in fact i will use then in some cases. But in others flexibility is escencial to me. So, wich are my options?

Thanks!

UPDATE 2

With the help of @LordTakkera and many people in this page i manage to start the development of my application. Rigth now I have my model, my wcf service my client and my first ViewVodel and View. Now i'm trying to add more complexity to the app adding multiple XAML views for my project. If I keept following MVVM pattern the navigation between this pages and the main page where all others views are inserted should also be manage with a viewModel (Something call application viewModel for what i read). My idea is to have a container MainPage with an area where child views will appear. I also wanted to have the child views in separated XAML file because some views are very complex and i will have losts of views! The problem is a can't find a single sample code for WPF navigation on MVVM pattern with a master container page. All the sample code that i could find:

1) Use external toolkit like Prism or MVVM ligth and right now i don't want to mess arround with new thing!

2) All the controls for each view are created on a single XAML.

I need some help with some code to create the basic layout of my app and want to know if what i'm planning is even posible. Thanks!

ericpap
  • 2,917
  • 5
  • 33
  • 52
  • A broad instruction: http://www.codeproject.com/Articles/30905/WPF-DataGrid-Practical-Examples – Silvermind Mar 11 '14 at 16:36
  • 2
    Unrelated to MVVM, but, forget `DataSet`. It is just a glorified `Dictionary` which forces you into all sorts of horrible `stringly typed` hacks and casting and introduces a bunch of ugly and runtime-error-prone code. Create a proper Strongly Typed Data Model and have your UI DataBind to proper Properties of that model. – Federico Berasategui Mar 11 '14 at 16:39
  • Sorry but i don´t understand. As i mention, my idea is to show the result of an SQL Server View into a GridView using MVVM. So if i understand correctly you telling me that i need to create a strong typed class to store the data insteed of DataSet. But in this case if the View change (i add one field for instance), i have to modify the model class, the viewmodel and the view and recompile all my code! That sound crazy to me! Isn't there a way to create abstract model, viewmodel and view? Thanks! – ericpap Mar 11 '14 at 17:20

1 Answers1

2

As HighCore noted, DataSet isn't a good choice of a Model, but otherwise that sounds about right, there are a couple of concerns I would have from your post though.

  1. You mention that you have variable "type" this is a large red flag. If you have variable types, how are you going to have consistent columns in your data grid? Now, if you mean that you are going to have a different data grid for each type (perhaps using typed Data Templates) then that would be ok.

  2. When you say "format the data" I hope you mean "store it in a data object". WPF binds to properties of objects, so your datagrid should look something like:

    <DataGrid ItemsSource={Binding DataItems}>
       <DataGrid.Columns>
          <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
          ...
       </DataGrid.Columns>
    </DataGrid>
    

Basically, make sure you bind to objects that are populated from your Model. The ViewModel is definitely the object that should be performing this translation.

Update

I apologize for not understanding the purpose of your application, in that specific application, what you are talking about makes more sense. That being said, I will try to address your concerns:

  1. In general, you should need to change your model/view/view model if the underlying data context or objects changes. C# is strongly typed, and the whole point of WPF is to have declarative, strongly typed UIs. I understand that you are trying to show "generic" data, but unless you are doing a "SELECT *" type query, you are going to need to change some code anyways. If you know what the view that you are displaying is, then changing all the code if a field is modified/added is perfectly acceptable (and even desirable, because it forces you to account for the change everywhere it affects).

  2. Variable, or "weak" types are a red-flag because, as noted above, C# is a strongly typed language. Strong typing has a lot of advantages, least among them good compile-time error checking. If you want to be in a weakly-typed environment, think twice about which language you are using.

  3. This goes back to the generic data. You can use typed Data Templates to accomplish some "formatting" changes based on type, but this is in a polymorphic (as opposed to weakly-typed) scenario. You could use a converter to perform the currency format you describe, but I would think about what you are trying to do and make sure that it is the direction you want to go.

Update 2 Strong typing should be just fine for this scenario. In fact, you are communicating with a WCF service, which by definition is strongly typed (this is the whole point of DataContracts, if you aren't doing it this way, please fix it and save yourself a lot of trouble). So we know your model (the WCF service) has strongly typed data objects, with properties like "Sales Date", "Client Name", "Sale Import", "Vendor Name", and "Sales per client". Now we just need three views (or even one flexible view) to accomplish your three scenarios.

You certainly do not need three binaries, even with the three views approach (you just need a way to select which view is active). You could even have an app config that determines which "client" to use, or load your views through MEF. The one flexible view approach takes a lot more work, because you have to bind your column collection instead of having it statically defined (a problem, incidentally, I am currently working on for one of my projects).

In short, there are many ways to have different views appear. I would not recommend changing the view based on the data, because your user wouldn't expect it, and it will be extremely messy to implement. If you want "Client 1" to only have access to "View 1" I would set it in the app config or only distribute the "View 1" plugin and load it using MEF. If all clients should be able to see all views, some kind of combo box or navigation bar is in order.

Update 3 Having (potentially) multiple views for the same view model, and especially multiple view models for the same model, is one of the reasons to use MVVM! I'm glad you were able to discover this. On to your questions:

As to your first comment:

  1. Your model (on the WCF side) won't have any knowledge of user filters, unless your request includes them. There isn't a problem with including that information (in fact I would encourage it to keep network utilization down), but you need to be aware of that when designing your service contract.

  2. View models always (without exception to my knowledge) live on the client side. The client-side "model" becomes the WCF proxy in your scenario.

As to your second:

  1. There is absolutely a way of creating data model classes from your Database, in fact, I would encourage it. .NET has a library called Entity Framework (currently at version 6.02, available on Nuget) that will automatically generate database "objects" with automatic foreign-key navigation and a host of other features (MSDN). A word of warning, EF classes, in general, can not be sent directly via WCF (due to the navigation properties, the recursion breaks the serializer). So, anything you want to send to your clients should be sent as a manually created DataContract, and a class on the server translates between the two.

  2. I don't know about a link, but having multiple views is pretty simple, you just use a Content Presenter and set the backing UserControl property whenever you want to change. It can also be accomplished by using a tab control, and probably an infinite number of other ways.:

    <ContentPresenter Content="{Binding CurrentView}"/>
    
  3. See my note above on using EF classes with WCF. Even if you don't use EF, in general it is recommended to use custom built data objects as your contracts. That way, you are only sending the information that is needed, and your contracts library isn't cluttered with database/model objects.

Update 4 1. Remember, you don't want to expose your database objects directly to WCF, and you especially don't want to do this with EF objects (because of the navigation properties). So you could: (A) use EF for your DAL and translate to Data Contract objects for WCF (recommended) or (B) create your own model objects, that could potentially be the same as the data contract objects (though I would still keep them separate) and do the DAL through ADO.NET or something similar. If you use EF, the database CRUD operations are very easy to do, as you noted.

  1. You only need a different view model if the data is different. If your view model consists of (primarily) a large collection of objects that the different views just display differently, then I see no reason to duplicate the code in multiple view models. The rule-of-thumb is: The View Model should be independent of the view. As long as you don't have any view specific code in your VM, you can reuse it for as many views as you want.

  2. Your final question is huge, and while I am happy to give you my opinion, you will find that if you asked 100 engineers this question, they would all give you different answers (as it seems you have already found).

So, to start with, you are absolutely right. Using MVVM (or any design pattern) will increase the amount of code you have to write, sometimes dramatically (especially when you are just starting a MVVM project, the amount of boilerplate code seems absolutely ridiculous at times).

However, the point of design patterns is not to make our code size smaller, it is to make it more extensible, maintainable, and testable. Specific to MVVM, you have the ability to put multiple views on the same view model (as you have seen) and the ability to put multiple view models on the same model. This means if you want to add a view or view model, you don't have to rewrite a whole bunch of code. Additionally, both the view model and model are easily testable since they have no knowledge of the UI.

In general, my rule of good design is Use Common Sense!. If it is likely to be changed/extended in the future, using a design pattern is almost always worth the extra code. If I am just going to throw it away in an hour, who cares?

Like I said, the applicability of design patterns and when deviations are ok is a huge debate in software engineering. I would encourage you to just go with what makes sense (thinking about the future of course) and refactor when you are wrong.

Please let me know if that addresses your concerns, of if you have more questions.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • 1) Wich is the alternative for dataSets that don't force me to modify Model, View and View Model if the data from the SQL View Change? 2) Why is variable types a red flag? 2) With "format the data" i mean change the way data is display on grid depending on Field Type from the view. If the field is currency, display the number with currency symbol, etc. Thanks! – ericpap Mar 11 '14 at 17:21
  • Thank you very much LordTakkera for your effort in traing to clarify my doubts. I edited the question to include some details on my scenario. What you think about it? Thanks again! – ericpap Mar 11 '14 at 19:23
  • @ericpap my attempt at addressing your update above. Let me know if I can provide anything else! – BradleyDotNET Mar 11 '14 at 20:04
  • Ok. I understand your point.I didn't know i could have one Model, o view model and multiple views. That seems like an interest approach giving the client the posibility of use multiples views for the same report. So to create my Sales report, i should:1) create the sp or view on the database; 2)Create a strong typed class model for store data; 3) Fill the model depending on user filters; 4)Create a Contract on WCF to expose some part of the model; 5) Create my ViewModel (On server? or Client side?); 6) Create multiple views on client and let user choose wich view to use, rigth? – ericpap Mar 12 '14 at 12:38
  • 3 Question regarding previuos comment: 1) Is there a way to automate the proccess o creating data model classes from a DB view o SP? or i need to create them by hand?; 2) Can you give some link with examples of multiple views and choossing between them? 3) Should i use expose my Model class directly to WCF or I need use a WCF especific class for that? Thank you again! – ericpap Mar 12 '14 at 12:46
  • @ericpap I tried to address your new comments in "Update 3" – BradleyDotNET Mar 12 '14 at 16:16
  • Great info! I will save this thread as a guideline for my project. All the info that you give me is great! The problem, is that with every answer you give me, i have new doubts: 1) So my server side will store data Model. For doing this i understand i have 2 opcions: A) Use EF with some kind of interface to WCF B) Have my own model class and expose it directly as the contract for the WCF Service rigth? In this case i have to create the class and manage CRUD operations manualy instead of EF in wich i can update my db directly using the EF class, rigth? (i read some info on EF and POCO objects). – ericpap Mar 13 '14 at 01:56
  • So going back to my example of sales report: In WPF i understand that the view is the XAML itself. So multiple view means multiple WPF forms. I could have two sales reports based on the same model, for example sales per client and sales per vendor. In this case i use one model and create 2 view models? Normaly i do this using distinct querys. I realy apreciate your help and this subject is very interest. But have to say that this aproach means tons of code for just showing some data on a grid, don't you think? In fact i read some criticism on MVVM tech on this mather. What you think of that? – ericpap Mar 13 '14 at 02:05
  • @ericpap my response to your questions in "Update 4". BTW, I am glad you are really thinking through all of this, by really understanding it you are helping yourself become a much better programmer/engineer in the future. – BradleyDotNET Mar 13 '14 at 16:35
  • Thank you very much @LordTakkera for sharing all this with me. I have more tan enougth to start my proyect, and i think all this thread is just great. Is there any way i can contact you for futher reference? I promise it only be as last resource. Also if i can help you en any way (Maybe some SQL) be free to contact me. Thanks again. – ericpap Mar 13 '14 at 21:55
  • If you post a comment here, I will see it and be happy to look at whatever problem you may be having. – BradleyDotNET Mar 13 '14 at 22:00
  • Great! Normaly to start learning a new technology my prefered method is to start with a good example and try to understand how it works. Searching the web i find this tutorial(http://www.software-architects.com/devblog/2010/09/10/MVVM-Tutorial-from-Start-to-Finish) that seems to cover all that we talk about from EF Data Models and WCF Service to WPF Views. Do you think is as good start point? Thanks! – ericpap Mar 14 '14 at 00:33
  • Hi @LordTakkera. I advance a lot in my Project. So far i manage to create my dataModel using EF, create a WCF contract to expose some method to list purchases orders from clients, build a simple viewmodel on client and use it to bind to a DataGrid on WPF. I did this without using code behind, creating propertys on viewmodel and raising PropertyChange. I also manage to filter the grid with a combobox showing clients. I have to say that the technology is a little complex at the beggining (especially viewmodel code), but is great! Now some questions: – ericpap Mar 15 '14 at 21:22
  • 1) How can a implement a more complex filters for orders? something like:"list orders from client 1 issued between 01/01/2014 and 01/30/2014 wich contain product A or B" when all the filters are optional? – ericpap Mar 15 '14 at 21:25
  • 2) Can i connect Entity Framework to multiple DB's wich has the exact same structure depending on user choice? (This is because I have separated DB's for each bussines unit). In this case can multiple client connect to multiple DB's using the same DataModel at the same time? Thanks! – ericpap Mar 15 '14 at 21:28
  • 3) This is more conceptual. In EF, should i add on each model all the tables that conform a logical object? For example if a create a EF model for purchase orders i also should add the table with products? In this case this table will belong to multiple logical model so i add it in every one that needit? Or is best to créate a huge model with all my tables in it? THanks!!!! – ericpap Mar 15 '14 at 21:33
  • 1) Absolutely, there are several ways to do this one that I just learned about is the Filter property of a collection view source: http://msdn.microsoft.com/en-us/library/system.windows.data.collectionview.filter(v=vs.110).aspx If you search on SO/google I'm sure you could come up with others (I posted my way somewhere, if I could only remember where...) – BradleyDotNET Mar 17 '14 at 04:40
  • 2) Yes, you can connect to different databases, but the schemas have to match EXACTLY. You just need to modify the connection logic to accept a coded connection string instead of relying on the app config. If you can't find anything post a question (feel free to leave me a link) and I'm sure someone will be able to help you. Multiple clients *could* connect to Multiple DBs, it just depends on your WCF service contracts. The WCF service function would have to collate the different data sets before returning them. – BradleyDotNET Mar 17 '14 at 04:42
  • 3) I would use good DB design, I have yet to need to modify a good DB to use EF effectively (in fact it works better on good, normalized databases). In general, you only want one schema. Trying to bridge between multiple schemas will generally end up being a GIANT rabbit hole. – BradleyDotNET Mar 17 '14 at 04:44
  • @ericpap, my reponses above in the comments. Glad you are making progress! – BradleyDotNET Mar 17 '14 at 04:45
  • Can you help me with this? http://stackoverflow.com/questions/22483578/expossing-entity-framework-over-wcf-service – ericpap Mar 18 '14 at 15:28
  • Looks like you got an outstanding answer. I could help a little with the refactoring, but it looks like TomTom has you going in the right direction :) – BradleyDotNET Mar 18 '14 at 16:13
  • Thanks for that. After Reading several times TomTom answer i´m starting to undestand his point. The last part of is answer is a Little confuse for me. He write: "I would use POCO DTO that are projected from LINQ queries and exposed as IQueryable preferably on an ODATA compatible WCF endpoint". So if i understand correctly the reason to expose the data as IQueryable is that i can add my where statement on client depending on User input, right? otherwise i can use IEnumeable. Thats the reason also for the need of an ODATA i think. But shouldn't be fieltering done in Business Layer? Thanks! – ericpap Mar 19 '14 at 01:47
  • OData is just a data transmission standard for web services. If you were going to use standard SOAP or TCP WCF, I wouldn't bother with it. As far as IQueryable goes, I honestly don't know exactly what it gets you. The LINQ extensions (like .Where) all work on IEnumerables. I would do filtering on the Server side if it at all makes sense (to keep network traffic down). Otherwise, filtering probably belongs in the view model (especially if it is user-defined and can't be done server-side). Let me know if I can help with anything else! – BradleyDotNET Mar 19 '14 at 05:40
  • Hi there! Can you comment something about the last update I did in this post? http://stackoverflow.com/questions/22483578/exposing-entity-framework-over-wcf-service. After a lot of reading i have re-write my app and want to know if i'm on the rigth path.Thank You! – ericpap Mar 28 '14 at 15:24
  • Hi! can you help me with my update on this post? thanks! – ericpap Apr 01 '14 at 16:15
  • What you are asking is absolutely possible, and I would be happy to answer it. Could you post as a new question? You may want some feedback from other members of the community as well :) – BradleyDotNET Apr 01 '14 at 16:36
  • Great Idea! Here it is: http://stackoverflow.com/questions/22793164/wpf-navigate-throug-views-using-mvvm-pattern – ericpap Apr 01 '14 at 17:48
  • Answered! Let me know what you think :) – BradleyDotNET Apr 01 '14 at 17:54