Author |
Share Topic Topic Search Topic Options
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Topic: DialogManager strategy? Posted: 03-Apr-2012 at 10:53am |
As you know, Cocktail is based on Caliburn.Micro, which is a VM-first framework firsts and foremost. CM can be used as a V-first framework for example on Windows Phone, where you have to use Microsoft's view-based navigation scheme in order to get your app approved, but a phone app is significantly less complex than a desktop app.
VM-first makes architecturally for a much cleaner separation of concerns. I would argue it doesn't get much better. All the navigation, decision etc. logic is in one place in the VM and the current state of the VM determines which V is displayed over it. The V is pure look-and-feel at that point and becomes completely replaceable. For example an Admin user could see a completely different view than a regular user. A view should never have logic in it. In fact you should delete all the code-behind files to not even be tempted to add logic to the V. It's all XAML and data-binding. You can hand the V to a designer and they can focus on making it look the best without having to deal with any dependencies on your code. If at some point you don't like the look and feel anymore you can simply replace it with new views without having to change the logic.
Another concern is UI composition. Composing a screen V-first gets messy trying to get the underlying VMs to coordinate with each other. Composing VMs is a lot easier and cleaner. Look at how highly decomposed the UI in TempHire is. Imaging how to wire the pieces up if the composition was driven by the V.
TempHire is really a good example to demonstrate the benefits of VM-first. If you compare TempHire Silverlight to TempHire WPF you'll notice that 99% of the code is shared. There are one or two places where a compiler directive was necessary to account for differences at the API layer, but other than that the difference between WPF and Silverlight is just at the View level. For example in WPF the root view is typically a Window, where as in Silverlight it's a UserControl that's hosted in the Silverlight plug-in. So, you'll notice that the WPF solution uses different Vs for about half of the VMs. The application logic is completely agnostic to the platform you are using. In fact TempHire started as a Silverlight only project. Then I got requests for a WPF version and it took less than a weekend to port it to WPF. Now I still need to port several styles over, but again that's all presentation. Once we have DevForce working in WinRT it will take very little effort to port TempHire to Metro. In this case it probably will take a littler longer because for Metro one should rethink the UI so it's touch friendly, but again most of that is isolated to the Vs.
|
|
Siyfion
Groupie
Joined: 22-Mar-2012
Location: Bristol, UK
Posts: 47
|
Post Options
Quote Reply
Posted: 03-Apr-2012 at 9:25am |
Ok, I may well give it a good look-over once I've finished wrapping my head around the rest of the framework.
As for your earlier comment about Cocktail being a ViewModel first, framework...
Could you please go into a bit more detail as to why this is the case? Perhaps highlight the pros/cons as to why ViewModel first was the preferred approach? We're debating the VM-First / V-First designs heavily here, and would really value a 3rd persons perspective... Especially as we are planning on using DevForce + Caliburn + Cocktail(if VM-First).
Also, I don't think that I noticed it state anywhere in the documentation that Cocktail is a ViewModel first framework, although from what I gather, VM first does seem to be more the "norm"? Perhaps it should be in the documentation somewhere (unless I've missed it?).
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 03-Apr-2012 at 3:19am |
It could, but that's not how the DialogManager currently works. The context complicates things, because you have to follow a different naming convention and the VM/V that calls the DialogManager has to be setup with the context as well, so that you can use the VM with different Vs. That would make the standard usage of the DialogManager more involved and complicated. That's not to say that there couldn't be additional signatures that would support the usage of the context. You are free to take a crack at it and submit it to CocktailContrib if you'd like.
https://github.com/marcelgood/CocktailContrib
|
|
Siyfion
Groupie
Joined: 22-Mar-2012
Location: Bristol, UK
Posts: 47
|
Post Options
Quote Reply
Posted: 03-Apr-2012 at 1:03am |
Ok not a problem, there are two developers working on the project at the moment and we both seem to prefer different approaches; he prefers View-First, I prefer ViewModel-First. I was just wondering if View-First was even supported in Cocktail, but that answers it!
On a related note, having multiple views for a ViewModel isn't unusual and in Caliburn the way they seem to allow for control of this is via setting the cal:View.Context="ViewContext" property on the content control that hosts the ViewModel. Could this not somehow be worked into the DialogManager so that a Context can be specified for the ViewModel passed in?
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 02-Apr-2012 at 10:19am |
Not with the DialogManager as it is. Cocktail as a whole is ViewModel first. I don't recommend View first. Can be done, but doesn't scale.
|
|
Siyfion
Groupie
Joined: 22-Mar-2012
Location: Bristol, UK
Posts: 47
|
Post Options
Quote Reply
Posted: 02-Apr-2012 at 3:45am |
Ok thanks for that, but just to clarify, there isn't a way to currently do a View-First Dialog Box?
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 30-Mar-2012 at 10:13am |
Originally posted by Siyfion
Aslo, do I actually need to create a new view model for the dialog explicitly? I mean, all the information is there in the viewmodel that launched the dialog, is there no way to launch it with a View instead of a ViewModel and attach it to the "launching" ViewModel? |
A VM is simply an object. The entity itself can be a VM. You just have to define a convention, so Cocktail knows how to find the V that goes with a given entity and then you can call the dialog manager with the entity instead of a VM that wraps the entity if you don't have any logic in between. But back to the previous post, you often have UI logic in between that doesn't belong into the entity like converting data for proper display. The HappyHour tutorial actually demonstrates how to use an entity directly as a VM. I forgot which lesson that is in, though.
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 30-Mar-2012 at 10:10am |
Originally posted by Siyfion
Thanks for that, that helped a great deal!
Perhaps you could offer some advice for a related problem?
In the dialog that is displayed, say that I have a few bits of information, call it the measurements of the DVD case that they want us to create for them to house the custom DVD they've ordered... Now internally, I store all of the measurements in mm, however a user has the option to change their preferences to display the measurements in mm, inches, cm, etc. whichever they prefer. Potentially there could be a large number of properties that have this same behaviour; width, height, depth, etc.
Normally I would use the asynchronous onSuccess operation when the DVD information is retrieved to update the values of the properties, as you are doing in the example you gave before. However, if the value has to be converted from the database value in mm, into a user value in inches, then I can't do that in the set operation of the property, otherwise when they type in a value in inches, it'll run through the conversion process again...? Or am I just getting my wires crossed?
|
You should never do this kind of conversion in the entity itself. The entity and the database should always hold the data in your internal format of choosing, in this case say mm. Then the VM has the responsibility to convert it back and forward depending on how the user wants to see it. You want to seperate how the data is stored from how the data is used. The entity holds the raw data. The VM/V controls how the user interacts and views the data. Proper seperation of concerns will make things a lot easier in the long run.
|
|
Siyfion
Groupie
Joined: 22-Mar-2012
Location: Bristol, UK
Posts: 47
|
Post Options
Quote Reply
Posted: 30-Mar-2012 at 5:07am |
Aslo, do I actually need to create a new view model for the dialog explicitly? I mean, all the information is there in the viewmodel that launched the dialog, is there no way to launch it with a View instead of a ViewModel and attach it to the "launching" ViewModel?
|
|
Siyfion
Groupie
Joined: 22-Mar-2012
Location: Bristol, UK
Posts: 47
|
Post Options
Quote Reply
Posted: 30-Mar-2012 at 4:31am |
Thanks for that, that helped a great deal!
Perhaps you could offer some advice for a related problem?
In the dialog that is displayed, say that I have a few bits of information, call it the measurements of the DVD case that they want us to create for them to house the custom DVD they've ordered... Now internally, I store all of the measurements in mm, however a user has the option to change their preferences to display the measurements in mm, inches, cm, etc. whichever they prefer. Potentially there could be a large number of properties that have this same behaviour; width, height, depth, etc.
Normally I would use the asynchronous onSuccess operation when the DVD information is retrieved to update the values of the properties, as you are doing in the example you gave before. However, if the value has to be converted from the database value in mm, into a user value in inches, then I can't do that in the set operation of the property, otherwise when they type in a value in inches, it'll run through the conversion process again...? Or am I just getting my wires crossed?
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 29-Mar-2012 at 11:42am |
No, I would suggest to add a Start method to the VM through which you either pass the ID of the selected DVD and then the VM loads it from the correct repository or if the popup is read-only then you could pass the entire entity into the Start method. I generally prefer passing IDs, to make sure the entity comes from the correct repository if you do sandboxing for example. You can see an example in TempHire in StaffingResourceSummaryViewModel.EditName(). It's not exactly your scenario, but conceptually the same. public IEnumerable<IResult> EditName()
{
StaffingResourceNameEditorViewModel nameEditor = _nameEditorFactory.CreatePart();
yield return _dialogManager.ShowDialog(nameEditor.Start(StaffingResource.Id), DialogButtons.OkCancel);
StaffingResource.FirstName = nameEditor.FirstName;
StaffingResource.MiddleName = nameEditor.MiddleName;
StaffingResource.LastName = nameEditor.LastName;
}
|
|
Siyfion
Groupie
Joined: 22-Mar-2012
Location: Bristol, UK
Posts: 47
|
Post Options
Quote Reply
Posted: 29-Mar-2012 at 10:38am |
And you would suggest that I simply pass the selected DVD through to the constructor? (Sorry, bit new to all this!)
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 29-Mar-2012 at 9:42am |
I assume the VM that launches the popup holds the entire list of DVDs. You have to create a VM that holds a single DVD object. You initialize that VM with the current selected DVD from the list and then hand it to DialogManager.ShowDialog, which in turn will show it as a popup. A VM can only be paired with a single V at any given time, so the VM that launches your popup is currently bound to the V that displays your list. It cannot also be bound to the popup V that displays the details. You need another VM instance for the popup.
|
|
Siyfion
Groupie
Joined: 22-Mar-2012
Location: Bristol, UK
Posts: 47
|
Post Options
Quote Reply
Posted: 29-Mar-2012 at 8:49am |
I don't know really where to ask this, but I'm hoping someone here will be able to help...
I am using the DialogManager class in the Cocktail project and I want to use it to display a properties window about a currently selected item. For example:
Imagine a view + viewmodel that displays a large searchable collection of DVDs with titles and a picture of the cover art. If you double click on a particular DVD, I want it to popup an information panel that shows further information about the selected item. I know that I need to create a View for the DialogManager to display with fields such as "Avg. Rating", "Description", etc.. but how do I go about creating a ViewModel for it?
Do I even need a ViewModel for it, as the VM that launches the popup has all the additional information available already...? If I do create another VM for it, how does it know which item it needs to get the information for?
|
|