I was hoping someone could sort this out for me. im trying my hardest to stick to the MVVM pattern as much as possible. yes i understand that this is a pattern and not a frame work.
so far after reading this is the Impression that i have. please advise if this is the wrong approach.
My project is basically a WMI browser that stores favorite queries and run multiple queries against computers and then compare results.
The View:
Is basically the XAML portion of the project. here we would bind the controls to the Model View including itemssource selected items and anything else that is required.
So the View has no access to the model view, it does not store data or manipulate data inside the model view. it only bounds to observable collections inside the model view
The Model View:
Is where and event triggers happen from client interaction, IE: selection item change or clicking a button. the Model view then uses the data the the model has gathered arranges the data in a view able context for the view.
The Model:
Gets the data required for the end users and stores the data for when the model view requires it.
Am i even close to right on this ?
View - XAML / Control Styling / Control Creation
Model View - Data Organisation / Event management / Data Display Management
Model - Data Gathering / Remote Connections to Data sources.
Sounds fine as long as your ViewModel are not actually dealing with view (WPF-specific) code.
Think of ViewModels as technology-agnostic. In theory, you should be able to run your ViewModels in a console or Android application, therefore any references or dependencies on System.Windows (WPF-specific) classes is unacceptable in the ViewModel level.
I figured this out. was a little easier than first anticipated.
public class ParentNode
{
public ParentNode() { }
public string ParentNodeName { get; set; }
public ObservableCollection<SubNode> AddChildNodes { get; set; }
public ObservableCollection<CheckBoxSubNode> AddCheckBoxChildNodes { get; set; }
}
public class SubNode
{
public SubNode() { }
public String SubNodeName { get; set; }
}
new ParentNode() {
parentnodename = "parent"
addchildnodes = new SubNode() { Subnodename = "subnode" }
)
Then some random XAML binding to bind to the correct propertes and all was good.
My View Model still doesnt directly access the View. :)
Related
I have a WPF application that displays a list of files/folders to the user in a treeview and they select which ones they want to load for the app. The ViewModel stores the folders/files in a DirectoryItem class that is binded to the UI:
public class DirectoryItem : INotifyPropertyChanged
{
public String DisplayName { get; set; }
public String Fullpath { get; set; }
public ObservableCollection<DirectoryItem> Children { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
The way I'm handling it now, the Model is passed a root directory and returns a List of string with every file in/under the root directory. Then, the ViewModel has a BuildDirectoryItemCollection function that converts the list into the ObservableCollection of DirectoryItems.
This is my first WPF app so I want to make sure I'm following the MVVM pattern correctly. Am I correct in thinking that the conversion from the List to ObservableCollection should take place in the ViewModel? Should the Model even have knowledge of the DirectoryItem class?
And as a side note, I'm not convinced that passing in a List of filepaths and then rebuilding the folder structure from that List is a good way of building my ObservableCollection. I am open to suggestions on a better way to do this!
Thanks for your time.
It's a bit unclear what your model actually is in this case, but since you are just creating DirectoryItem objects based on the structure of a folder on disk, you might as well do all this, i.e. build the ObservableCollection<DirectoryItem>, directly in the view model class.
So you could for example inject the view model class with the path of the root directory (a string) and create the ObservableCollection<DirectoryItem> that you bind to in the view directly in the constructor of the view model.
It seems unnecessary to first build a List<string> and then build an ObservableCollection<DirectoryItem> based on this list instead of building the ObservableCollection<DirectoryItem> immediately.
A method that creates a hierarchical collection based on a file path is perfectly fine to implement in the view model. Don't overcomplicate things :)
I have an API which sends error status flag, error message and object of user. Currently I am using the API response class to get these responses.
public class UsersResponse
{
public int Status { get; set; }
public string Message { get; set; }
public List<User> Users { get; set; }
}
I receive the response in the instance of the above mentioned class and later display the result on the view. I get the response in the view's code behind file.
I was wondering if this is the right way to do it? If view models are used, will it be tackled by view model? If yes, then how will it be done.
I am thinking of getting into the habit of using view models rather than fully relying on the views code behind file.
The best way to tackle such a situation will be of great help and highly appreciated.
Thanks :)
Expose a INPC property like IsBusy in the ViewModel, turn it on before accessing your long running process (better make it async), then turn it off.
You shouldn't be loading data in the code-behind, in MVVM the code-behind should be minimized and restricted to view-specific only code (e.g. if you have several platforms). Think of code behind like JS for HTML, even less than that.
It's the ViewModel that should take care of loading the data and manipulating it. ViewModel = The model of the view.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have some kind of experience with WinForms coding but I am trying to do my new stuff with WPF (and the mvvm pattern).
One thing I am going round in circles for days searching the internet is to get the following right:
What do I have to implement in a model and what in the viewmodel when it goes down to "manage the repository (model?) data".
(I think) I do understand the basic concept of mvvm and decopeling all the data but I struggle to figure out the right implementation.
Let's assume I have an existing service (application without any UI) which is able to read values from a (ini) configuration file, do some stuff what its intended for, and write configurations to the local registry. Perhaps in future I want change the configuration to be stored in xml or json instead of ini. From my point of view this is all well placed in the existing code - let's say a configuration.cs file with a class configurations - which currently has absolutely nothing to do with my new wpf console application I want to implement next.
namespace ExistingConfigurationCode
{
public enum Setting
{
some,
values
}
public class ConfigurationItemProperties
{
public property1
public property 2
}
public class ApplicationConfiguration
{
List<ConfigurationItemProperties> config;
public void LoadConfig()
public void SaveConfig()
}
}
As just said, now I do want to implement a UI to enable a user to set up those configurations.
For what I have understand until now is:
the view is only the view and contains no logic at all
the viewmodel is responsible to "deliver" all needed informations to the view and receive commands from the view
the model is a model of the data we are dealing with
My problem in understanding (and knowledge how to proceed) is:
is this existing class already my model? But it does not make sense to add all the RaisePropertyChange stuff in this class because it is also used in the service. Also I have seen a lot of tutorials where I am told to not put any code in the model
if the existing class should be in my view model, what do I need the model for than?
Should the model have only a reference to my already existing class and control all read and write stuff to the registry/xml/ini through some kind of a wrapper?
Where do I have to add the "RaisePropertyChange" getter and setter? Because they are "controlling" the UI I would guess they should be placed in the view model, but I have seen a lot of examples where they are also in the model?
I got some kind of stuck here.
I thought the binding should be between the view and the view model, so the RaisePropertyChange should be in the view model, but in this case I would have to recreate everything a second time in the view model
Additional informations in response to comments
I understood now, that I can use my existing code as the model.
Besides the already existing "execution engine" which is utilizing the existing namespace/class, I have to create two applications with UI. An "admin console" and an end user console.
(I think) I am fine with the admin console, because it has a view for all the properties of ConfigurationItemProperties, so I can following Fabios first explanations.
But the second UI for the end user should have a stripped down UI, probably a listview with some checkboxes per list view item. And here is my problem.
For the listview I need the ObservableCollection, but for the items in the list view I need the "facade" fabio mentioned. Am I right so far?
If so, the ObservableCollection AND "ConfigurationItemPropertiesFacade" are working with the "model" which does not have any implementation of INotifyPropertyChanged or INotifyCollectionChanges stuff. But I think the "collections" must refer to the "single items" from the facade because the collection (from the view model) has no reference to the facade in the view model.
Try to think about MVVM like about three layers(not files) of your application.
View - namespace/project which contains only view logic(XAML and code
behind)
Model - namespace/project which contains all "business logic"
ViewModel - namespace/project which contains logic to link View and
Model without knowing about View's namespace. Another words ViewModel layer's responsibility to be a bridge between Model and View - Call Model's method, raise PropertyChanged event for when some value changed to inform View about changes.
So keep all your logic of configuration in the Model namespace.
In case when Model class need to be represent in the View with editing possibilities, create Facade class in the ViewModel layer
public class ConfigurationItemPropertiesFacade : INotifyPropertyChanged
{
private ConfigurationItemProperties _Model;
public string Property1
{
get { return _Model.Property1; }
set
{
if(Equals(_Model.Property1, value)) return;
_Model.Property1 = value;
RaisePropertyChanged();
}
}
public ConfigurationItemPropertiesFacade(ConfigurationItemProperties model)
{
_Model = model;
}
}
Use ConfigurationItemPropertiesFacade class as ViewModel in the View.
With this approach your Model layer stays clean and can be used anywhere.
In response on comment:
So tutorials telling it is not allowed to put "code" in the model are wrong, right?
Again try thinking about Model in MVVM not like a one class/file, but layer/namespace/project which can contains more then one class.
There is no right or wrong - you can implement your logic as you fill better suite your specifications. But if you will respect Single responsibility principle (https://softwareengineering.stackexchange.com/a/17170/102569), then you will separate responsibilities of ApplicationConfiguration to (I didn't know inner logic of methods Load and Save)
"Model" class which represents only data, class which has no
functionality just properties for keeping data.
You have this already ConfigurationItemProperties
"Service" classes which contains functionality of saving and loading
configurations. Your class can be spitted in two classes.
// Have one responsibility take configurations as parameter and save them somewhere
public class SaveService
{
public void Save(List<ConfigurationItemProperties> items) {}
}
// Have one responsibility load configurations and return them to the caller
public class LoadService
{
public List<ConfigurationItemProperties> Load() {}
}
So then your ViewModel will use those classes to represent and modify configurations in UI.
public class ViewModel
{
private readonly LoadService _LoadService;
private readonly SaveService _SaveService;
//Here you can use your"Facade" implementation
private ObservableCollection<ConfigurationItemPropertiesFacade> _Items
public ObservableCollection<ConfigurationItemPropertiesFacade> Items
{
get { return _Items; }
set
{
_Items = value;
RaisePropertyChanged(nameOf(Items));
}
}
public ICommand Save { get; set; }
public ICommand Load { get; set; }
public ViewModel(LoadService loadService, SaveService saveService)
{
_LoadService = loadService;
_SaveService = saveService;
// Create command instance for Save
// Create command instance for Load
var itemsList = _LoadService.Load();
var facadeItems = itemsList.Select(item => new ConfigurationItemPropertiesFacade(item));
Items = new ObservableCollection(facadeItems);
}
}
Let's think about these definitions:
Model - Data access and business Logic.
ViewModel - it's responsibility is to provide model's data and logic to view in such way that is easily consumable from view.
I believe that these definition gives you clear answer:
ExistingConfigurationCode class should be considered as part of your model.
Few more thoughts however:
INotifyPropertyChanged and INotifyCollection changed is not limited to DataBinding or WPF. These interfaces are much more general.
There nothing wrong about implementing INotifyPropertyChanged in a Model if you want your model to notify other layers or compoments about changes
It's common practice that you bind your Views directly to Model entities. ViewModel often just expose entity from Model as a property.
Wrapping model properties in ViewModel is one way of doing it. Another way is having separate properties in ViewModel with their own backing fields. You set the ViewModel properties to initial values when user visits the page and you save the edited values back to Model when user clicks save.
Being rather new to ASP.NET MVC, I am already seeing some benefits of it for code reuse and maintainability. When asking a previous question on routing, I had another idea for my example, but unsure how to implement it.
Question: How can I reuse my issue view and controller in separate pages, as well as having parameters for certain things (like how many issues to display)?
Example: Say in my web application I want to show a list of issues. These issues are grouped by projects. So if you go to www.example.com/projectname/issues, you would see a list of issues for that project, and if you went to www.example.com/issues, you would see all issues for all projects. What I would like to do is that if you go to www.example.com/projectname, you would see some info about that project, including the last 10 issues submitted.
How can I reuse this issue code? I see I have the option for Partial View, but when I implemented it, I was unsure how to route any code to it. In Web Forms, you could make a ASP.net control, set some parameters in the code behind, and then embed this control elsewhere.
Some of the examples I have found so far either lack a complete implementation (goiing beyond just adding some HTMl in other pages), look like older MVC code that doesn't seem to work for me in ASP.NET MVC 3, and lack allowing me to set paramaters and showing this type of reuse.
My terminology may not be entirely correct here. If anything, I am trying to find the best (read MVC) way to replicate something like ASP.net Web Forms User Controls. As in, reusing my 'issues' code (HTML and C#) on both a 'master' issues list, as well as an issues 'widget' if you will
Skip the temptation write code in the view that goes out and accesses data on it's own. That includes using built-in functions like RenderAction. Even though RenderAction "goes back" to execute another controller it doesn't mean the view isn't taking an action on its own, which arguably breaks the MVC approach where views are supposed to do nothing and the model is supposed to contain everything the view needs.
Instead what you could do is send back a model for your issue list page(s) which contains a property containing the issues list:
public class IssueListModel {
public List<Issue> Issues { get; set; }
}
Populate it in your issue list action:
public ActionResult IssueList(string projectName) // projectName may be null
{
var issueListModel = new IssueListModel();
issueListModel.Issues = SomeRepository.GetIssues(projectName); // whatever you need to send...
return View(issueListModel);
}
Then on your list pages you could loop through it:
#foreach (var issue in Model.Issues) {
<div>#issue.IssueName</div>
}
Or you could send the Issues collection down to a partial view:
#Html.RenderPartial("IssueList", Model.Issues)
You can type your partial view to expect List as the model:
#model List<MyProject.Models.Issue>
... and then loop through it in the partial view, this time doing a foreach on the model itself:
#foreach (var issue in Model) {
<div>#issue.IssueName</div>
}
Then what you can do is make a separate model for your project detail view which also contains a property containing Issues:
public class ProjectDetailModel {
public Project Project { get; set; }
public List<Issue> Issues { get; set; }
public string Whatever { get; set; }
}
In the controller you can populate this List using the same function that you would populate in your lists controller:
public ActionResult ProjectDetail(string projectName)
{
var projectDetailModel = new ProjectDetailModel();
projectDetailModel.Issues = SomeRepository.GetIssues(projectName, 10); // whatever you need to send
return View(projectDetailModel);
}
Then you can re-use the same exact partial view on your ProjectDetail view:
#Html.RenderPartial("IssueList", Model.Issues)
A long answer but I hope this is what you were looking for!
If you want to re-use presentation logic only, you can use partial view. If you want to re-use also controller's logic, you have to use child action combined with partial view.
Create a controller
public class IssuesController : Controller
{
[ChildActionOnly]
public PartialViewResult List(string projectName, int issueCount = 0)
{
IEnumerable<Issue> issueList = new List<Issue>();
// Here load appropriate issues into issueList
return PartialView(issueList);
}
}
Do not forget also to create appropriate partial view named List within the folder Issues.
Finally use this line within your project view
#{ Html.RenderAction("List", "Issues", new { projectName = "Px", issueCount = 10 } ); }
and this line within your issue list view
#{ Html.RenderAction("List", "Issues", new { projectName = "Px" } ); }
In your controller method return the view as named rather than just View()
ie...
public ViewResult IssueView1()
{ return View("Issue");}
public ViewResult IssueView2()
{return View("Issue");}
I am trying to implement MVVM in a new project (based on WPF & Prism) in which almost every screen (view) will have a search screen shown first where the user may choose to add/edit records.
The search screen takes a refernce to the VM which implements one of my interfaces ISearchProvider (which has one method IEnumerable Search(string criteria)).
Should this Search method return
a collection of VM's (with their models properly set) which will get shown in the grid in the search screen or
just Models so that when the user chooses to edit a record (Model), the chosen model is given to an instance of a VM which then gets edited or
some third option?
Whatever you plan to show to user should be wrapped with View Model.
You mentioned that user will select model to edit. This should be view model; user will select model (entity) to edit, but what he'll be shown (or what your view will see) should be list of view models representing some entity. User (or in this case view) should not need any knowledge of actual model.
Now, the view model should not be doing any search itself. It should delegate search to component that's responsibility is to perform search and return result (be it some kind of DAO, your custom tool - options may vary). What is more, the same view model should also be responsible for "feeding" view with data that may or may not arrive from search.
To give it code example:
public class UserListViewModel : ISearchProvider
{
private IUserFinder userFinder;
public UserListViewModel(IUserFinder userFinder)
{
this.userFinder = userFinder;
}
public ObservableCollection<UserViewModel> Users { get; private set; }
public void Search(string criteria)
{
var users = this.userFinder.Search(criteria);
// rebuild users collection - view will get notified of any changes
// made to .Users property as it is ObservableCollection
}
}
Also, it's probably good idea to make ISearchProvider interface expose single Search command. This way, binding from view is really simple.
To sum up, 2 simple points:
make sure your search logic is not in view model; let view model delegate the search
make search results be a part of view model or actual view model objects (so you can "feed" them to view easily)
My preference is to show ViewModels in the grid especially if you have a ViewModelBase class with a DisplayName that implements INPC and IDataErrorInfo. It's rare that my Model perfectly captures all the semantics of the presentation, and the VM is how we keep those concerns separate.
HTH,
Berryl