I'd like to implement a sort of Addressbook/Contactbook using a Datagrid (or a List) and the MVVM pattern.
Something like in Outlook/Thunderbird, where you've a list of your contacts displayed with a 2-3 main fields (name surname for example), and when you double-click a contact, then you get a new modal box that displays all the details of this specific contact.
In fact my scenario is much more similar to an application that manages Customers, Orders and Products. The user would have as main view 3 datagrids showed through 3 tabs, one shows the list of Customers, one the Orders and one the Products.
Then in each view, you can Add (through opening an extra dialog), Delete (under certain conditions) an object.
Each object has a relation with another one.
For example, in a Customer instance, I've a list of Orders for that Customer and for each Order a list of Products ordered.
Since a couple of weeks/months, I'm reading a lot of stuff about MVVM pattern on the net, but somehow, I get confused. Until now, I could find any sample like this. (perhaps, I searched wrong?)
I'd like to implement something like this using the MVVM pattern.
How could I organize such an application?
Could someone help, how to structure it?
Is there a sample somewhere?
Thx in advance for your help.
Fred
1) This video helped me with understanding the basics of MVVM.
2) Search on SO for "MVVM Master Detail".
3) "Delete (under certain conditions) an object": read about Commands and Relay Commands:
private RelayCommand _delete;
public ICommand Delete
{
get
{
return _delete ?? (_delete = new RelayCommand(action => DoDelete(), condition => CanDelete));
}
}
private bool CanDelete
{
get { return true; // your condition }
}
4) "Then in each view, you can Add (through opening an extra dialog)"
"Each object has a relation with another one" - you need to let other ViewModels know of changes. Typical solution is to use Mediator pattern. Please refer to following articles:
http://sachabarber.net/?p=477
http://marlongrech.wordpress.com/2008/03/20/more-than-just-mvc-for-wpf/
http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx
Edit: just found another nice and simple MVVM sample featuring sorting filtering and list navigation:
http://marlongrech.wordpress.com/2008/11/22/icollectionview-explained/
This article about Catel includes a "Person application". It is very simple, but allows you to manage a list of contacts. Maybe it's a starting point for you.
Related
I have the next issue.
I have a custom object called 'Application', and I have this requirement:
"Show all Contacts related to an Application. Create a field on Application object, must be read only".
I solve it with apex code. 'Application' has a lookup to Opportunity, Opportunity to Account, and all my contacts have AccountId, so this way, I get all the contacts using apex code in a trigger.
But, I've been ask to change this to a Formula field in Application object.
So, my issue is next. I'm not able to get all contacts with advance formula editor, because they're not part of any object. I have no master-detail relationship.
Does any one know how can I achieve this using configuration? I should not use apex code for this req.
Thank in advance guys.
I don't think you can do it.
In formulas / merge fields syntax there's no way to go "up, up then down" (Application -> Opportunity -> Account -> down to Contacts related list). There's also nothing that would let you loop through Contacts (and display what? Ids? Names? Emails?). Roughly speaking you can only go up through dots.
You might want to explore path of "cross object workflow" rules but I imagine that when I add a new Contact to Account it should somehow "spread itself" to all related Applications? There's no straight way to fire a workflow on delete too - so you'd eventually end up with inaccurate list.
I'd say trigger was a good solution. Maybe it ws unoptimized but if it has to be in a field - tough.
There might be a fairly simple way of achieving that by embedding a visualforce page within Application page layout.
This should be doable with pure Visualforce (so technically there will be no Apex code ;))
Something as simple as
<apex:relatedList list="Contacts" subject="Application__c.Opportunity__r.AccountId" />
would be a good start (if you want your own layout and not a rel. list - you should be still able to pull it off with <apex:repeat> or <apex:pageBlockTable>.
There's one BUT here: it's not a field, just a display trick. Forget about using it in reports, mobile applications etc.
Another way - would it be acceptable to be 1 click away from these contacts? You could make a report "Account with Contacts", filter it by Id of one Account and later use "URL hacking" to change the filter depending on from which Application you'll click it. This link could be either a formula field or a real custom button/link. Technically - it's pure config, no apex & VF.
You can read more about URL hacking at Ray Dehler's excellent post and specifically about dynamic Reports here or here.
what is the best way to load dropdown lists from reference/lookup tables for a desktop application?
the application is layed out into 3 tiers. I've built up my entities.
the front end has a form with 6 tabs. and one big save (another discussion :)
Should I load them all when the form is initially loaded? Are there any caching mechanisms I could use?
it is vb.net app on a network drive that is accessed by several users.
it's also worth noting that some reference tables may be updated. Via another form.
thanks
T
Lots of factors. One you need to populate in constructor so the data is there to populate the visual elements. Beware that just because a tab is not visible does not mean it is not loaded when you app starts.
For a static list of strings
public class Library : INotifyPropertyChanged
{
private List<string> dropDown1;
public List<string> DropDown1 { get { return dropDown1; } }
public Library()
{
// use data reader to populate dropDown1
}
}
I know this will get comments that can use something lighter than a List but List has a lot of nice features, easy syntax, and easy to populate. As a next step you could structure as a client server and use some static so the list is populated once and then shared by all. If you have more properties then substitute string with a class. For a dynamic list then in the get you grab the current data from the table on demand. In your get you could hold on to the last list and if the next request is within X seconds then return stale data. It depends on if stale data is acceptable.
There are many other approaches and I do not pretend this is the best. Just putting out a relatively simple example to get you started.
When it gets to hierarchical then things get a little more complex. There you can use ADO.NET table to store the static dependent data and then apply a filter on a view.
If its a web page you don't have to load all tabs on page load.
Desktop i think it will be more easy and it should be like that.
Only when the user click on the tab show the page and hide all the pages
associated for other tabs.
i hope all tab pages values will be on session so that user can go and come back to any tab and your Big Save at last.
Something useful related to your question i found here
http://www.syncfusion.com/FAQ/windowsforms/faq_c93c.aspx
and one more
the title pretty much explains my issue:
I am right now taking care of drag & drop in my app. I can have many instances of my app running at the same time, and I can drag from one instance to the other without trouble.
Now, I would like to know if I'm drag & dropping "internally" (i.e: the drop occurs in the same instance as the drag) or "externally" (the opposite)
I went this far: I need to add to my dragged data a unique ID (something like a PUID) that identifies the app where I'm making the drag. Then I can just compare this id to the one I have locally on the drop and see if it is the same.
I have no problem transferring such info in my drag Data, the issue is more to find this UId.
I have been thinking using the Process.GetCurrentProcess().MainWindowHandle; but I'm not sure if this is a good idea.
What option(s) do I have to make this work?
I would simply create a readonly Guid that gets set when you start your app.
You can put this wherever your main logic lives (MainWindow or ViewModel).
Here is a snippet:
public class MyViewModel
{
private readonly Guid mUID = Guid.NewGuid();
// In case you want a property for it
public string UniqueApplicationID
{
get { return mUID; }
}
public void OnDropHandler(MyViewModel objectBeingDropped)
{
if (objectBeingDropped.UniqueApplicationID == mUID)
return;
// Handle drop normally here
}
}
The D-n-D is much like an UI activity, than an internal one.
I would distinguish two contexts: dropping a file, and dropping some object (e.g. VS designer). In the first context there's no problem at all, because it doesn't matter where you pull the data. In the second case, you should know what object has been chosen. For instance, you have a listbox with many items (e.g. the alphabet chars), once the user D-n-D any of those items, the internal operation is a simple reference to the selected object. By pulling the data from another app, you won't be able to find your object, because the source is different.
In case of structs or strings, you may wrap them with a GUID, as you correctly proposed.
I am building a silverlight app. My requirement is to have Users select a number of skills that apply to them, from a larger list of skills.
Tables: Candidate => CandidateSkills; SkillsCategories => Skills. I think the schema is self explanatory. The front end will show all skills (grouped into different categories), and when the candidate logs in, only his selected skills will show in the check boxes. Fairly simple.
My question: Do I bring all the Skill entities to the front end and then get the CandidateSkill entities, loop through them and set the checkboxes accordingly or is their a easier/better way?
Thanks
I recommend building a class to use as a ViewModel. The class should contain at least a property to indicate whether the item is selected, the text to present, and either the model entity itself or its key.
You can create the set of view model objects by left-joining the set of all skills to the individual candidate's skills, and setting IsSelected to the result of a non-null test on the candidate skill.
You can then bind directly to the ViewModel.
I had a similar situation (Users to Permissions instead of Candidates to Skills) once, and I used this resource as a starting point. I hope it helps.
In my case, I had a "Save" button which, upon click, would run some code-behind code to iterate through the selected items and submit them to my Web service. Without knowing the details of your data and service implementation, I'll not clutter up the post with the nitty-gritty details.
Best of luck!
Comments for Discussion
Here is a pseudo-LINQ procedure creating view models by issuing two database calls:
var userskills = database.CandidateSkills
.Where(cs => cs.UserId == someUserId)
.Select(cs => cs.SkillId)
.ToList();
var skills = from s in database.Skills
select new CandidateSkillViewModel()
{
Text = s.SkillName,
IsSelected = userskills.Contains(s.SkillId),
Value = s.SkillId
};
mylist.ItemsSource = skills;
This would give you a bindable data source. Ultimately, using this pattern, you'll have to translate selections/deselections into inserts/deletes by hand. For me, I do this in the handler for the button click. I retrieve a fresh set of candidate skills, iterate through the items of the list, and insert/delete instances of CandidateSkill as needed.
I realize that depending on a button click to resolve my viewmodel state into database operations might not be considered by purists to be complete MVVM, but it worked for me.
I hope this helps a little more.
I am working on a Silverlight application using RIA services with Entities Framework.
Forgive me, i'm fairly new with Ria services, but how do i go about getting a list of objects from the db without doing a load operation?
Example: I have an Employees table, in this table there's a IsSupervisor flag. I want to show a list of employees in a grid with a combobox cell bound to a list of supervisors (employees where isSupervisor = true).
The problem i have is that when the list of supervisors come back, the employee list only displays supervisors.
I hope this makes sense....
It's hard to really say without seeing your code, as RIA Services is pretty darn flexible.
It sounds like you are binding a DataGrid to your DomainContext's Employee EntitySet, and then making two calls to the server, one to get all employees, then one to get supervisors. If this is the case then yes your second call can wipe out the first one (depends on how you have LoadBehavior set).
But if you are querying the db to get all employees, then you already have the supervisors on the client side. Just create a separate collection that only contains the supervisors, and bind the ComboBox to this. Something like:
private void OnEmployeesLoaded(LoadOperation<Employee> loadOp) {
if(!loadOp.HasError) {
Employees = new List<Employee>(loadOp.Entities);
Supervisors = new List<Employee>(loadOp.Entities.Where(e => e.IsSupervisor));
}
}