I was wondering if it is possible to group properties of a c# class.
Something like the following:
public class Computer
{
//First Group
public string Name{get;set;}
public string IPAddress{get;set;}
//Second Group
public string Driver1Name {get;set;}
public string Driver1Port{get;set;}
}
The model I have returns 70 columns or so (i.e. the model has ~ 70 properties) and I would like to return all of these to display to the user. Clearly, 70 properties is too much display on one page, and so the contents of this page will be tabbed based on the groupings of these properties (using jquery).
My initial thought was to use attributes, and group by the attributes. But I would like to open this up for other suggestions. Please let me know your thoughts on how I could achieve this.
Cheers!
You could use attributes. Either use your own, or the existing attributes that are used by the object browser:
System.ComponentModel.CategoryAttribute.
Related
I just developing a personal project and actually I'm using EF Code First from database and I'm facing a little problem.
The problem simply is I want to define an attribute called Download and this attribute may contain multiple download links for example :
Attribute Name : Download
=>Values :
link1.com
link2.com
link3.com
How to define this in my model an attribute that can hold many values and how can I show them in my view one by one like foreach or something to fetch the attribute values and split them
Thanks and I hope someone help me with that!
You can either use a single string with a separator, or create another table linked to this one:
class Download
{
...
public string Link {get;set;}
}
class ParentClass
{
...
public virtual ICollection<Download> Links {get;set;}
}
Then in your view, you can iterate over the list of Links.
I am about to upgrade our software from ASP.NET WebForms to .NET MVC. All over the web it shows how to create a view based on a model, which is fine.
In this project the users can hide properties of the model to generate a view suitable for them, yet another client in another website and hide other properties.
The code is all the same, but i would like to know if there is a way to hide/show properties of a model based on a condition easily, hopefully without having a lot of IF statements all over my views.
Example - How can 1 client see only name and town, yet another client see all 3 properties. Just need to show based on a condition.
public class MyObject() {
public property name { get; set; };
public property town { get; set; };
public property customText { get; set; }
public MyObject() {}
}
NOTE: Users can also determine the order of these properties, can i do that as well easily ?
Just to say that creating separate views is not possible. The above is a very simple example of a model with properties. Our models can have about 100 properties, and the user can turn these on and off whenever they like, so it needs to be able to be done dynamically
Is there a way of creating a ViewModel on the fly?
Thanks in advance
Create a Property class or similar and model you data appropriately:
public class Property
{
public string Name {get;set;}
public bool Visible {get;set;}
public int Order {get;set;}
}
Then your view model can be similar to your example:
public class ViewModel
{
public Property Name {get;set;}
public Property Town {get;set;}
public Property CustomText {get;set;}
}
Well you cannot bind multiple models to your view.Obviously you have to do workaround in your view based on user roles.
Or else create a seperate model and view for each user roles.
I have been working on a project called Dynamic MVC.
http://dynamicmvc.com
It currently does not do what your asking. The functionality is already there, it is just not exposed the way you need it. However, if you are interested I will add the functionality so you can pass the properties you want to display in the querystring. Eventually, a customizable dynamic view will generate your page for you without any coding required. Also, the order of the properties would determine the order on your page. This would work for any model with the DynamicEntity attribute.
Let me know if your interested and I can include it in the next release.
I'm trying to insert properties dynamically to a class.
I need to load properties from database and show it in PropertyGrid, but I want to it to be build in run time, it means that I want to insert property definition to database and to load it to a class(My Class) in runtime.
e.g - if the data base contains row that define property (e.g Name of type string)
the class should something like this:
public MyClass
{
public string Name{get; set;}
}
I also tried to do it using dynamic but it failed.
any ideas?
Thank you.
You can use an ExpandoObject.
I would use Simple.Data to do this. It fetches data from the database and constructs dynamic objects from the query :)
In my MonoDevelop project I have an iPhone app. I have two different views. Each view contains a UITable. For view 1 I have class 1 hooked to the UITable as Datasource 1. For View 2 I have a class 2 hooked up as Datasource 2. Both classes (i.e. Datasources) feed the tables with data. View 2 also has a custom cell and because of this loads asynchronous.
I get the data from 2 XML files using linq to XML. Everything works and the data loads great. What I need to do know is to load data in Datasource 2 based on the selection made in View 1. To do this I need to pass an ID from view 1 to Class(Datasource) 2. Problem.
I have tried just about everything I know but I just can't get it right.
The correct solution according to me:
I have created another class called SelectedRound with two properties. Code:
using System;
namespace xxxxx
{
public class SelectedRound
{
public string RoundID { get; set; }
public string Date { get; set; }
}
}
When I set RoundID in class 1 then I can access it in class 1. Trying to access it in class 2 however, returns nothing or null. Why would this happen? Could it be because Class(Datasource) 2 is loading asynchronously? Should I instantiate the SelectedRound class in some global way? If so how? AppDelegate maybe? (I am struggling to do that as well).
It seems pointless to me that setting and getting a simple string variable is difficult.
This feels like it is all about how you are passing the SelectedRound instance from the first view to the second.
As a very quick and dirty solution you could just use a singleton or could just use a static class:
public static class SelectedRound
{
public static string RoundID {get;set;}
public static string Date {get;set;}
}
For a more sophisticated pattern, then try overriding the constructors of one or both of your two view controllers in order to pass them a shared instance of your non-static class.
The view controllers may feel foreign to you right now - but they are just c# classes - so feel free to extend them by writing overrides, new methods and properties.
Many tutorials say that when i have to pass data from controller to view the best way is to create a flattern viewMoldel.
This solution came to solve also other problems (like the eager loading problem).
My concern is that when i create a flatten viewModel I lose all the informations that I store in the entities via annotation.
Suppose that i have a model composed by
class product{
[DisplayName("Name")]
public String Name{get;set;}
[DisplayName("Image")]
public String Image{get;set;}
[DisplayName("Description")]
public String Description{get;set;}
public String CategoryId{get;set;}
}
class category{
[DisplayName("Code")]
Public String Id{get;set;}
[DisplayName("Category name")]
public String Name{get;set;}
}
To render a grid that show product informations many tutorials say that the best way is to provide a flatten viewModel like this:
class productGridViewModel{
Public String ProductName{get;set}
Public String ProductImage{get;set}
Public String ProductDescription{get;set}
Public String CategoryName{get;set}
}
My concern is that I need to write again all the DisplayName annotations in the viewModel.
If you are flattening your model entities into ViewModels, shouldn't the attributes be removed from the model entity classes and placed on the ViewModels? Your model entities will not be used for display, so they should not have those attributes.
One simple solution is to have read-only properties in the viewModel which read the meta-data of the underlying Model object. Then you can bind this meta-data with the appropriate control in the View.
As below:
class productGridViewModel{
Public String ProductName{get;set}
Public String ProductImage{get;set}
Public String ProductDescription{get;set}
Public String CategoryName{get;set}
public string ProductDisplayName
{
get
{
//Please dont mind this code.. I am sure you can write it in much better way.
return typeof(Producy).GetProperty("Name").GetCustomAttributes(typeof(DisplayName))[0].ToString();
}
}
}
Your view model is your data consumption use case. If you need metadata then the view model flattened or otherwise will need to support it. May be you need to add it dynamically? Or if that's too onerous, then you need to encode it at compile time.
Edit.
You can use T4 transformations to ensure that dependent code it kept up to date. In fact we use this allow users to customise the DB and thus allow express the customisations in the view models.
What you do is put the source of the truth in one assembly, and then use a T4 transform file to create other representations from this assembly using reflection in another assembly.
The way to do it would be by implementing a custom AssociatedMetadataProvider. This isn't as much work as you'd think, and you could implement one to generate metadata from an xml file, database, convention, or even buddy types like the current one does.
The only thing you'd need to do differently to the current implementation is allow buddy types to contain field/properties which don't exist on the model they apply to, because that is the only thing currently preventing you from creating a buddy type which you could apply to all view/editor models of your particula model.
Its a bit of work and depends how much time it would save you but don't forget most of the MVC source code is available and you wouldn't have to change very much
Martin