Databind a List with a Template to a Dropdown Datasource - c#

I have a Template via:
public class OwnedProvinces
{ public Guid ProvinceID;
public string ProvinceName;
}
And I created a list with this template here:
List<OwnedProvinces> getinfo = (from upi in db.Utopia_Province_Data_Captured_Gens
where upi.Owner_User_ID == SQLStatementsCS.UserID()
where upi.Province_Name != string.Empty
select new OwnedProvinces { ProvinceName = upi.Province_Name, ProvinceID = upi.Province_ID}).ToList();
The problem with this when I try to bind it to the Dropdown list like so:
ddlSelectProvince.DataTextField = "ProvinceName";
ddlSelectProvince.DataValueField = "ProvinceID";
ddlSelectProvince.DataSource = getinfo;
ddlSelectProvince.DataBind();
It throws the Error:
DataBinding: 'OwnedProvinces' does not contain a property with the name 'ProvinceName'.
Basically, it can't find the property ProvinceName in the List, but makes no sense to me. If I do an anonymous query, it works, but when I assign it to the class OwnedPRovinces, it throws this error...

Try to change the class like this
public class OwnedProvinces
{
public Guid ProvinceID { get; set; }
public string ProvinceName { get; set; }
}
The problem is that ProvinceID and ProvinceName are member variables not properties.

Problem is with your declaration -
public Guid ProvinceID;
public string ProvinceName;
are the fields, but not the properties. You should either change their definition or you should try to implement the IDataBindable interface, as written here:
http://www.primaryobjects.com/CMS/Article95.aspx
#region IDataBindable Members
public List<NameValueType> ToList()
{
List<NameValueType> resultList = new List<NameValueType>();
using (DataContext context = new DataContext())
{
List<Monster> itemList = context.Monsters.ToList();
foreach (Monster item in itemList)
{
resultList.Add(new NameValueType(item.MonsterId.ToString(), item.Name));
}
}
return resultList;
}
#endregion

Related

Create object of type specified in a string

I have a bunch of classes generated by EF that are simple tables and have similar structures:
public class Contact
{
public int ID { get; set; }
public string Description { get; set; }
}
public class Member
{
public int ID { get; set; }
public string Description { get; set; }
}
I've also got a method for returning an object of a specified type:
public T GetInstance<T>(string type)
{
return (T)Activator.CreateInstance(Type.GetType(type));
}
What I want to do is something like this:
public ActionResult GetAll(string ClassType) // ClassType will be the name of one of the classes above
{
Object LookupType = GetInstance<Object>(ClassType);
List<LookupType> AllList = new List<LookupType>();
AllList = repo.GetAll<LookupType>().ToList<LookupType>(); // some generic method that will return a list;
}
This makes the compiler mad because I'm using a variable (LookupType) rather than a true type to build the list. However, neither of these work either:
List<LookupType.GetType()> Items = new List<LookupType.GetType()>();
List<typeof(LookupType)> Items = new List<typeof(LookupType)>();
Both cause an error - "Using generic type List requires 1 type argument".
Is there a proper way to do this? Is there a way to convert ClassType directly to a type without first making it an object (from which I hope to derive the type)?
Try using the CreateInstance method
SomeObject someObject = new SomeObject();
Type type = someObject.GetType();
Type listType = typeof(List<>).MakeGenericType(new [] { type });
IList list = (IList)Activator.CreateInstance(listType);
You cannot do it with C#!!
Compiler must to know the parameter type.
In that maybe you would like to accomplish, interfaces will help you
public class Contact: IIdDescription
{
public int ID { get; set; }
public string Description { get; set; }
}
public class Member: IIdDescription
{
public int ID { get; set; }
public string Description { get; set; }
}
public interface IIdDescription
{
int ID { get; set; }
string Description { get; set; }
}
public ActionResult GetAll(string type)
{
var AllList = new List<IIdDescription>();
if(type == Member.GetType().Name)
AllList = repo.Set<Member>().Cast<IIdDescription >().ToList();
if(type == Contact.GetType().Name)
AllList = repo.Set<Contact>().Cast<IIdDescription >().ToList();
...
}
and into your view use interface as model, something like
#model IEnumerable<IIdDescription>
If you don't know the type ahead of time maybe using a list of dynamic objects can help.
var item = GetInstance<Contact>("Namespace.Contact");
var items = new List<dynamic>();
items.Add(item);
You can then access the types like so...
Contact contact = items[0];
Just be aware that using dynamic can be expensive.

How to return the result of a stored procedure into a list in my view model

This is my first question here and I'm new to WPF/MVVM.
What I'm trying to do is display a multi-column listview that holds the results returned from a stored procedure.
I'm doing my best to implement MVVM and this is where I'm having trouble.
I have a model (SL_ID is the PK and not nullable in the database):
public class mJob_Select_OrderList
{
public int SL_ID { get; set; }
public string E32JobNumber { get; set; }
public string E32_CLIENT { get; set; }
public string SL_DESCRIPTION { get; set; }
public string E32_DESCRIPTION { get; set; }
}
and then I have a view model:
public class vmJob_Select : vmMain
{
#region Members
Models.mJob_Select _mJobSelectSettings;
public SLEVEN_CLASS.dbSLEVENDataContext _dc;
#endregion
#region Constructors
public vmJob_Select()
{
_dc = new SLEVEN_CLASS.dbSLEVENDataContext();
_mJobSelectSettings = new Models.mJob_Select { EnvironmentID = 1 };
//EnvironmentList
var dsEnvironmentList = (from el in _dc.vw_EnvironmentLists orderby el.ENV_ID select new mJob_Select_Environment { ENV_ID = el.ENV_ID, Environment = el.Environment, IMAGE_RESOURCE = el.IMAGE_RESOURCE });
EnvironmentList = new ObservableCollection<mJob_Select_Environment>(dsEnvironmentList);
//Orders List
var dsSLEVENOrders = _dc.get_SLORDER_List(SelectedEnvironmentID).ToList();
SelectOrderList = new List<mJob_Select_OrderList>(dsSLEVENOrders);
}
#endregion
#region Properties
public Models.mJob_Select mJobSelectSettings { get { return _mJobSelectSettings; } set { _mJobSelectSettings = value; } }
public int SelectedEnvironmentID { get { return mJobSelectSettings.EnvironmentID; } set { if (mJobSelectSettings.EnvironmentID != value) { mJobSelectSettings.EnvironmentID = value; RaisePropertyChanged("EnvironmentID"); } } }
public ObservableCollection<mJob_Select_Environment> EnvironmentList { get; set; }
public List<mJob_Select_OrderList> SelectOrderList { get; set; }
}
So basically EnvironmentList is pulled from a view in the database and I can populate an ObservableCollection successfully. The SelectedOrderList is the result of a stored procedure and I'm trying to load this result into a list object of some sort.
The error I'm getting is
Cannot convert from 'System.Collections.Generic.List' to 'int'
I was able to implement this successfully in the code behind on the view but I'm trying to adhere to MVVM and making my ViewModel do the work.
using (SLEVEN_CLASS.dbSLEVENDataContext dbSLEVEN = new SLEVEN_CLASS.dbSLEVENDataContext())
{
var dsSLEVENOrders = dbSLEVEN.get_SLORDER_List(intENVID);
lvSlevenJobs.ItemsSource = dsSLEVENOrders;
lvSlevenJobs.SelectedValuePath = "SL_ID";
}
I've been searching and trying to figure this out for awhile now and I've tried to implement some solutions that I've found here and there to no avail. One involved looping through the IResult and adding each row to the model another suggested building a more complex linq query instead of a stored procedure. None of these options are out of the question. Is there a generally accepted method for performing this task?
Thanks in advance to any answers/suggestions you can provide!
//EDIT//
I believe I've found my solution. I was trying to return my SPROC results to a model that I created but when using LINQ a Model is created automatically called Procedure Name + 'Result'.
I declared my list to utilize the 'Result' model like so:
public List<get_SLORDER_ListResult> SelectOrderList { get; set; }
List<get_SLORDER_ListResult> lstSLEVENOrders = _dc.get_SLORDER_List(SelectedEnvironmentID).ToList<get_SLORDER_ListResult>();
SelectOrderList = new List<get_SLORDER_ListResult>(lstSLEVENOrders);
I then bound my ListView to SelectOrderList.

How to get total Sum of my Collection/Class

I have this class:
public class ExtraDisplayItems
{
public int ItemId { get; set; }
public string ItemCode { get; set; }
public string ItemDescription { get; set; }
public double? ItemSellingPrice { get; set; }
}
I then add data to the class with the method below:
using (TruckServiceClient TSC = new TruckServiceClient())
{
var item = cmbAddExtras.SelectedItem as ExtraDisplayItems;
if (item != null)
{
var displayItem = new List<ExtraDisplayItems>
{
new ExtraDisplayItems
{
ItemId = item.ItemId,
ItemCode = item.ItemCode,
ItemDescription = item.ItemDescription,
ItemSellingPrice = item.ItemSellingPrice
}
};
dgAddExtras.Items.Add(item);
}
}
Now what I want to do is create a read-only property where I would get the total Sum of the ItemSellingPrice, but in this property I cannot reach the Sum when trying to calculate the double?
This is how I wan't the coding to work:
public double? SubTotalExtras
{
get { return ExtraDisplayItems.Sum(x => x.ItemSellingPrice); }
}
But... it's giving me the error:
ExtraDisplayItems does not contain a definition for 'Sum'
How would I go about fixing this?
EDIT
I have changed the class to:
public class ExtraDisplayItems
{
private List<ExtraDisplayItems> displayItems;
public int ItemId { get; set; }
...
}
And...
if (item != null)
{
this.displayItems = new List<ExtraDisplayItems> //Error
{
new ExtraDisplayItems
{
...
}
};
dgAddExtras.Items.Add(item);
}
But it now throws the error: does not contain definition for 'displayItems'
It seems dat ExtraDisplayItems is an instance of the ExtraDisplayItems class, which doesn't implement IEnumerable<T> (that is: 'it is a collection of something'). That means that it indeed doesn't have a Sum method, nor does the extension method apply.
My best guess at the moment is that you should save the displayItem (which is a List<ExtraDisplayItems>, so it implements IEnumerable<ExtraDisplayItems>) somewhere in your view model and call Sum on that.
Also, use naming conventions: you are making plurals singular and the other way around... Very confusing...
You are probably missing Linq in your using definitions.
using System.Linq;
EDIT:
I was assuming ExtraDisplayItems was a collection, then it is common to have the error 'x does not contain a definition for 'Sum'' even if you see it in code samples.
In order to do the sum various objects you actually need a collection of them not a single object.

Using Reflection and GetValue problems

I have an abstract class that looks like so:
public abstract class PageObjectsBase
{
public abstract string FriendlyName { get; }
public abstract string PageObjectKeyPrefix { get; }
public abstract string CollectionProperty { get; }
}
And a class that derives from PageObjectsBase:
public class PageRatingList : PageObjectsBase
{
public IList<PageRating> PageRatings { get; set; }
public PageRatingList()
{
this.PageRatings = new List<PageRating>();
}
public override string CollectionProperty
{
get
{
var collectionProperty = typeof(PageRatingList).GetProperties().FirstOrDefault(p => p.Name == "PageRatings");
return (collectionProperty != null) ? collectionProperty.Name : string.Empty;
}
}
public override string FriendlyName
{
get
{
return "Page feedback/rating";
}
}
public override string PageObjectKeyPrefix
{
get
{
return "pagerating-";
}
}
}
And a PageRating class which PageRatingList.PageRatings is holding a collection of:
public class PageRating : PageObjectBase
{
public int Score { get; set; }
public string Comment { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
The PageRatingList is being stored in a database (EPiServer's Dynamic Data Store, more specifically using the Page Object Manager). I need to create some reporting functionality and am essentially loading all reports that derive from PageObjectBase. When it comes to returning the data, the code will never know at compile time what type of data it is to load, so I am using Reflection. In my reporting class I have:
//this gives me the right type
var type = Type.GetType("MyNameSpace.PageRatingList", true);
var startPageData = this._contentRepository.Get<PageData>(startPage);
PageObjectManager pageObjectManager = new PageObjectManager(startPageData);
//this loads the instances from the DB
var props = pageObjectManager.LoadAllMetaObjects()
.FirstOrDefault(o => o.StoreName == "Sigma.CitizensAdvice.Web.Business.CustomEntity.PageRatingList");
//this gives me 4 PropertyInfo objects (IList: PageRatings, string : CollectionProperty, string :FriendlyName, string : PageObjectKeyPrefix)
var properties = props.Value.GetType().GetProperties();
I can then iterate through the PropertyInfo objects using:
foreach (var property in properties)
{
//extract property value here
}
The issue I am having is that I cannot figure out how to get the value of each of the propertyinfo objects. In addition, one of those properties is type List and again we wont know the type of T until runtime. So I also need some logic that checks if one of the PropertyInfo objects is of type List and then provides access to each of the properties in the List - the List being of type PageRating.
Can anyone help here? I've not really used reflection in the past so I am winging my way through it, rightly or wrongly!
Many thanks
Al
I may be missunderstanding the problem, but i think you may use something like this:
var props = new PageRatingList(); /*actual instanse of the object, in your case, i think "props.Value" */
var properties = typeof(PageRatingList).GetProperties();
foreach (var property in properties)
{
if (property.PropertyType == typeof(IList<PageRating>))
{
IList<PageRating> list = (IList<PageRating>)property.GetValue(props);
/* do */
}
else
{
object val = property.GetValue(props);
}
}
Hope this helps to find your solution.

C# Razor Viewmodel with Generic <T>?

I'm trying to make a streamlined viewmodel that I can dynamically generate some html based off of. However, I don't quite understand how (or if it's even possible) to create a viewmodel with a dynamic value.
My viewmodel:
public class DataGridViewModel<T>
{
public List<T> DataList { get; set; }
public List<HeaderValue> DataHeaders { get; set; }
public DataGridViewModel(List<T> dataIn)
{
DataList = dataIn;
SetHeaders();
}
public void SetHeaders()
{
//Build a list of column headers based on [Display] attribute
DataHeaders = new List<HeaderValue>();
var t = DataList.First().GetType();
foreach (var prop in t.GetProperties())
{
var gridattr = prop.GetCustomAttributes(false).FirstOrDefault(x => x is DisplayAttribute);
var head = gridattr == null ? "" : (string) gridattr.GetType().GetProperty("Name").GetValue(gridattr);
var visible = gridattr != null;
DataHeaders.Add(new HeaderValue()
{
Header = head,
Visible = visible,
Property = prop.Name
});
}
}
}
My controller:
var docdto = DocumentService.FetchDocuments(); //Returns IQueryable<DocumentDTO>
var vm = new DataGridViewModel<DocumentDto>(docdto.ToList());
return View(vm);
DocumentDTO:
public class DocumentDto
{
public Int32 DocumentId { get; set; }
[Display(Name = "Category")]
public string CategoryName { get; set; }
}
//These could be very different, based on the table they're modeled after.
View:
#model DataGridViewModel<T>
#foreach(var header in Model.DataHeaders)
{
<h1>#header.Property</h1>
}
The issue I'm having is, it seems the view cannot use a generic or dynamic value, and must be assigned to a base class. The problem then is that the DTOs are all very different.
Is this possible to do with Razor?
Thank you for your time :)

Categories