I'm beginning with Caliburn.micro and I'm a bit confused. Say I have a UI with 2 panes, e.g. (this is a fake sample) CustomersView and CustomerView, and 2 corresponding VM's, CustomersViewModel and CustomerViewModel.
Now, say I want to include both panes into a main shell, which should be able to access all the VM's like data members: e.g.
public class MainViewModel
{
private CustomerViewModel _vmCustomer;
private CustomersViewModel _vmCustomers;
...
}
As viewmodels are created by CM, how can I connect my main shell to each instance of them? Or is this a wrong approach? I do not need a conductor in its canonical sense here, as I'm not activating or deactivating a set of panes like in a MDI: I have a SDI UI with some panes, each backed by its VM, and a main shell which should manipulate all them. What is the right approach in a similar scenario?
In your MainView.xaml add two ContentControls and give them names that match the names of two properties representing your ViewModels.
ViewModel:
public CustomerViewModel CustomerViewModel { get; set; }
public CustomersViewModel CustomersViewModel { get; set; }
View:
<ContentControl x:Name="CustomerViewModel" />
<ContentControl x:Name="CustomersViewModel" />
Another way to do it is
public CustomerViewModel Customer { get; set; }
and
<myApp:CustomerView cal:View.Model="{Binding Customer}/>
This gives a reader a better idea what to expect from the view. Blendability could be better, too.
Related
I have a ViewModel which is used for a Wizard containing two separate ViewModels which are used to load partial views into the wizard. Depending on the option selected on Step1, I need to validate either Step2 or Step3. The viewmodels for Step2 and 3 have their own AbstractValidator which works great because it includes client side validation. The problem is that if I use ModelState.IsValid, one of the VMs always fails to validate because it's empty (that step was not filled out). Is there a way to skip validation for one of the viewmodels?
Say you have the following model:
public class PersonViewModel
{
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string FullName { get; set; }
}
But you want to exclude FullName from the model validation because you are using the model also in a place where FullName is not filled in, you can do so in the following way:
ModelState.Remove("FullName");
Hope to help, my friend :))
The solution I eventually arrived at was surprisingly simple but I didn't spot it in the docs. You can call $('#somecontainer').valid() which will show validation messages for supported controls and also return true if all controls in the container are valid. It doesn't work for everything as rules like GreaterThan aren't supported client side.
I have a CustomersController and in the Detail.cshtml view I need to display a list of that Customer's contacts and a list of that Customer's locations. I have a Detail(int? id) ActionResult and I have access to my CustomerService from within the controller. As of now in my Detail ActionResult I am able to do:
var cust = _custService.GetCustomerById(id);
return View(cust);
How would one recommend getting the rest of my lists in the view. I think I will create a GetContacts(customerID), GetLocations(CustomerID) within my CustomerService and then call them just like I call GetCustomerByID above. If I were to do it this way how would I have access to these lists in my view.
The next thing I was thinking about was possibly creating a ViewModel that has all of the basic customer properties like customer.Name, customer.Phone but then trying to figure out how I also make sure the ViewModel has the customer's contacts and locations. Would I just add 2 more properties to the ViewModel like customer.contacts and customer.locations since EF6 will make them available to me?
Any suggestions on the best way to go about getting multiple lists of information related to an entity in a view? Customer contacts and Customer locations are both one-to-many
The best practice is using a view model to transfer the data, as you have thought about.
public class CustomerDetailViewModel {
public string Name { get; set; }
public string Phone { get; set; }
public List<Contact> Contacts { get; set; }
public List<Location> Locations { get; set; }
}
I'm working with ASP.NET MVC 4, but I on't think that matters for the purpose of this question.
I have a relatively complex model for my edit view. Like this:
public class Recipe_model
{
public string Name { get; set; }
public List<Recipe_Ingredient_model> Ingredients { get; set; }
}
where Ingredients is
public class Recipe_Ingredient_model
{
public int RecipeID { get; set; }
public int? UnitID { get; set; }
public double? Quantity { get; set; }
public Ingredient_model Ingredient { get; set; }
}
which itself contains the Ingredient model.
When I make a form for this, the built-in Html.EditorFor() doesn't work for anything past the properties of the Recipe_model, so I'm using partial views to display the editor for each of the sub-models.
That works fine as far the interface goes, but when I submit the form to the controller and try to bind to the Recipe_model automatically using
[HttpPost]
public ActionResult Edit(Recipe_model model)
{
return View(model);
}
it fails because the ids of the input elements in the partial views do not conform to the correct pattern (I think ParentModel_Property).
Short from hard-coding the ids in the partial view or binding manually from the FormCollection in the controller, is there some way to get the correct ids generated in the partial view so that the model will bind automatically on submit?
This is common problem. Instead of simple partials, use EditorTemplates (special folder for models) and binding will work automatically.
For example look at this question: Updating multiple items within same view
in addition to the answer given by #WebDeveloper
you can also try and create a custom model binder though a little more complex but will add to the ease of posting and binding form value to the objects in long run
have a look here http://patrickdesjardins.com/blog/asp-net-mvc-model-binding
you will have to manually take all the form values and bind them to the model once and then you will be able to use the #HtmlFrom methods on the razor to do anything and you will get all the value inside the objects inside the action methods as you like.
A developer can be affected to 0 or more task. A task needs at least one developer to be executed. How do I express that in Code first?
public class Task
{
public int ID
//more properties here
public virtual ICollection<Developer> Developers { get; set; }
}
public class Developer
{
public int ID
//more properties here
public virtual ICollection<Task> Tasks { get; set; }
}
Thanks for helping
It's still a regular many-to-many relationship, and it should get mapped correctly by default. Specific business (validation) rules do not change its nature.
You can implement IValidatableObject if you want to enforce specific cardinalities when saving.
I would like to rename a navigation property and access that object in code by the new name I gave. I have renamed one of my user properties to a more meaningful name rather than 1,2,3...etc.
In this example, I have renamed OGSMUser5 to OGSMUserResponsible in the model diagram.
I then tried to access this in code, but it can't find my renamed property OGSMUserResponsible.
#contImprovement.OGSMUserResponsible.FullName
When I look at the code in the model generated from Entity Data Model, I see that the code did not change for the newly renamed model, which explains why I can't access it.
public virtual OGSMUser OGSMUser { get; set; }
public virtual OGSMUser OGSMUser1 { get; set; }
public virtual OGSMUser OGSMUser2 { get; set; }
public virtual OGSMUser OGSMUser3 { get; set; }
public virtual OGSMUser OGSMUser4 { get; set; }
public virtual OGSMUser OGSMUser5 { get; set; }
I have seen somewhat similar questions to this, but the answers I have seen I can't believe is the only option. They have been manually creating a new property with the name you want (what I renamed mine to in the navigation property) in a partial class and return the navigation property with the number in the name to help clean it up. I can't believe that this is the best way to accomplish what I am looking for.
Thanks for the help.
You probably didn't run the T4 template transformations.
Just right click your .tt files (they are under your .edmx file in the Solution Explorer tree) and run them. Alternatively, you can run all tt by clicking the button in Visual Studio's toolbar.