I have a arraylist of employees from the gridview in my ASP.net Page as shown below:
ArrayList tempempList = new ArrayList();
List<Employee> emps = new List<Employee>();
for (int i = 0; i < gvemp.Rows.Count; i++)
{
if (((CheckBox)gvemp.Rows[i].FindControl("cbAssign")).Checked)
{
tempempList.Add(((Label)gvemp.Rows[i].FindControl("lblempSeqNo")).Text);
}
}
Now I have List and Employee object consists of the following properties
empID, empName,empAge,empSalary
Now for each empID from tempempList I need to populate the List
I am not sure how I can populate emps.
Appreciate your help
The List<T> object is just the strongly-typed version (generic) of ArrayList. ArrayList is preserved for traditional purposes, and List<T> should be utilized when necessary.
You can call the List<T>.Add() method, just like you did for the ArrayList.Add() method. So something like:
emps.Add(yourValue);
That should suffice.
I'm building/updating an EntityFramework EntityObject on runtime. I want to set the properties of the entity class, property names and values are coming from another source.
So I'm doing this;
public static EntityCollection<T> UpdateLocaleEntity<T>(EntityCollection<T> entityCollectionToUpdate, params ILocaleControl[] values) where T : EntityObject
{
foreach (var x in entityCollectionToUpdate)
{
Type t = typeof(T);
dynamic localeEntity = x;
string cultureCode = localeEntity.CultureCode;
for (int j = 0; j < values.Length; j++)
{
var value = values[j].GetLocaleValue(cultureCode);
t.GetProperty(values[j].EntityPropertyName).SetValue(localeEntity, value, null);
}
}
return entityCollectionToUpdate;
}
So, how can I get rid of "t.GetProperty(values[j].EntityPropertyName).SetValue(localeEntity, value, null);" part, is there a dynamic way of doing this?
Something like;
dynamicCastedLocaleEntity.GetProperty(values[j].EntityPropertyName) = value;
Thanks.
Long answer coming up.
Reflection is great in many situations, horrible in some but in almost all cases it's slow.
There are at least 4 different ways to set a property in .NET without having to use reflection.
I thought I demonstrate one of them: Using compiled expression trees. Note that the expression building is rather expensive too so that's why it's very important to cache the delegate one builds with it in a dictionary (for instance):
Expression Trees was introduced in .NET35 and is used for many things. Here I use them to build a property setter expression and then compile it into a delegate.
The example demonstrates different timing for the different cases but here are my numbers:
Control case (hard coded): 0.02s
Reflection: 1.78s
Expression Tree: 0.06s
using System;
using System.Linq.Expressions;
namespace DifferentPropertSetterStrategies
{
class TestClass
{
public string XY
{
get;
set;
}
}
class DelegateFactory
{
public static Action<object, object> GenerateSetPropertyActionForControl(
)
{
return (inst, val) => ((TestClass) inst).XY = (string) val;
}
public static Action<object, object> GenerateSetPropertyActionWithReflection(
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
return (inst, val) => propertyInfo.SetValue (inst, val, null);
}
public static Action<object,object> GenerateSetPropertyActionWithLinqExpression (
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
var propertyType = propertyInfo.PropertyType;
var instanceParameter = Expression.Parameter(typeof(object), "instance");
var valueParameter = Expression.Parameter(typeof(object), "value");
var lambda = Expression.Lambda<Action<object, object>> (
Expression.Assign (
Expression.Property (Expression.Convert (instanceParameter, type), propertyInfo),
Expression.Convert(valueParameter, propertyType)),
instanceParameter,
valueParameter
);
return lambda.Compile();
}
}
static class Program
{
static void Time (
string tag,
object instance,
object value,
Action<object, object > action
)
{
// Cold run
action(instance, value);
var then = DateTime.Now;
const int Count = 2000000;
for (var iter = 0; iter < Count; ++iter)
{
action (instance, value);
}
var diff = DateTime.Now - then;
Console.WriteLine ("{0} {1} times - {2:0.00}s", tag, Count, diff.TotalSeconds);
}
static void Main(string[] args)
{
var instance = new TestClass ();
var instanceType = instance.GetType ();
const string TestProperty = "XY";
const string TestValue = "Test";
// Control case which just uses a hard coded delegate
Time(
"Control",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionForControl ()
);
Time(
"Reflection",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithReflection (instanceType, TestProperty)
);
Time(
"Expression Trees",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithLinqExpression(instanceType, TestProperty)
);
Console.ReadKey();
}
}
}
For FuleSnabel's answer, you can speed it up a lot (sometimes twice as fast in my tests). In some tests, it was just as fast as the Control solution:
public static Action<Object,Object> GenerateSetPropertyActionWithLinqExpression2(Type type, String property) {
PropertyInfo pi = type.GetProperty(property,BindingFlags.Instance|BindingFlags.Public);
MethodInfo mi = pi.GetSetMethod();
Type propertyType = pi.PropertyType;
var instance = Expression.Parameter(typeof(Object), "instance");
var value = Expression.Parameter(typeof(Object), "value");
var instance2 = Expression.Convert(instance, type);
var value2 = Expression.Convert(value, pi.PropertyType);
var callExpr = Expression.Call(instance2, mi, value2);
return Expression.Lambda<Action<Object,Object>>(callExpr, instance, value).Compile();
}
possibly not with EntityObject, but if you've had an ExpandoObject than you can do
dynamic entity = new ExpandoObject();
(entity as IDictionary<String, Object>)[values[j].EntityPropertyName] = value
The open source framework ImpromptuInterface has methods to invoke based on a string using the DLR rather than reflection and runs faster than reflection too.
Impromptu.InvokeSet(localeEntity, values[j].EntityPropertyName,value);
I'm afraid not. Any use of a dynamic object is baked-in at compile time. Any call which could vary at run-time has to be done using reflection.
I'm trying to write a more generic method that will populate either an ASP.NET dropdownlist OR a telerik RadComboBox with states. I'd like to pass the control in as a parameter to the method. I have a DataTable that holds all the states, which I loop through (see below) - I'd like to make this applicable to a Telerik RadComboBox - so I need to change the first parameter, and also the part where I Insert a new ListItem - for Telerik RadComboBox it is new RadComboBoxItem. How can I do this?
public void PopulateStates(DropDownList ddlStates, string country)
{
ddlStates.Items.Clear();
DataLookup dl = new DataLookup();
DataTable dt = dl.GetStatesByCountry(country);
if (dt != null)
{
if (dt.Rows.Count > 0)
{
ddlStates.Items.Insert(0, new ListItem(""));
for (int i = 0; i < dt.Rows.Count; i++)
{
ddlStates.Items.Add(new ListItem(dt.Rows[i]["STCD_Descr"].ToString(),
dt.Rows[i]["STCD_State_CD"].ToString()));
}
}
}
}
I looked up the telerik documentation & there doesn't seem to be common way of doing - what you are trying to do.
If it is possible, try using the databinding (setting the DataSource & calling DataBind).
Note: I haven't tried it. But I think that should be supported by both.
Since ListBox and RadComboBox does not have common classes except for the "Control" class you will need to check the actual type.
How about the following code?
public void PopulateStates(Control ddl, string country)
{
object listItem = new object();
switch (ddl.GetType().Name)
{
case "RadComboBox":
listItem = listItem as RadComboBoxItem;
ddl = ddl as RadComboBox;
break;
case "ListBox":
listItem = listItem as ListItem;
ddl = ddl as ListBox;
break;
default:
return;
}
// proceed with your code
}
I am calling a web Method from javascript. The web method returns an array of customers from the northwind database. The example I am working from is here: Calling Web Services with ASP.NET AJAX
I dont know how to write this javascript method: CreateCustomersTable
This would create the html table to display the data being returned. Any help would be appreciated.
My javascript
function GetCustomerByCountry() {
var country = $get("txtCountry").value;
AjaxWebService.GetCustomersByCountry(country, OnWSRequestComplete, OnWSRequestFailed);
}
function OnWSRequestComplete(results) {
if (results != null) {
CreateCustomersTable(results);
//GetMap(results);
}
}
function CreateCustomersTable(result) {
alert(result);
if (document.all) //Filter for IE DOM since other browsers are limited
{
// How do I do this?
}
}
else {
$get("divOutput").innerHTML = "RSS only available in IE5+"; }
}
My web Method
[WebMethod]
public Customer[] GetCustomersByCountry(string country)
{
NorthwindDALTableAdapters.CustomersTableAdapter adap =
new NorthwindDALTableAdapters.CustomersTableAdapter();
NorthwindDAL.CustomersDataTable dt = adap.GetCustomersByCountry(country);
if (dt.Rows.Count <= 0)
{
return null;
}
Customer[] customers = new Customer[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
NorthwindDAL.CustomersRow row = (NorthwindDAL.CustomersRow)dt.Rows[i];
customers[i] = new Customer();
customers[i].CustomerId = row.CustomerID;
customers[i].Name = row.ContactName;
}
return customers;
}
Try to look what is the result variable value in debug mode. If the structure seems the structure that i'm imagining, something like this could work:
function CreateCustomersTable(result) {
var str = '<table>';
str += '<tr><th>Id</th><th>Name</th></tr>';
for ( var i=0; i< result.length; i++){
str += '<tr><td>' + result[i].CustomerId + '</td><td>' + result[i].Name + '</td></tr>';
}
str += '</table>';
return str;
}
And then You can do somethig like this:
var existingDiv = document.getElementById('Id of an existing Div');
existingDiv.innerHTML = CreateCustomersTable(result);
I wish this help you.
Something like this, assuming you have JSON returned in the "result" value. The "container" is a div with id of "container". I'm cloning nodes to save memory, but also if you wanted to assign some base classes to the "base" elements.
var table = document.createElement('table');
var baseRow = document.createElement('tr');
var baseCell = document.createElement('td');
var container = document.getElementById('container');
for(var i = 0; i < results.length; i++){
//Create a new row
var myRow = baseRow.cloneNode(false);
//Create a new cell, you could loop this for multiple cells
var myCell = baseCell.cloneNode(false);
myCell.innerHTML = result.value;
//Append new cell
myRow.appendChild(myCell);
//Append new row
table.appendChild(myRow);
}
container.appendChild(table);
You should pass the array as JSON or XML instead of just the toString() value of it (unless that offcourse is returns either JSON oR XML). Note that JSOn is better for javascript since it is a javascript native format.
Also the person who told you that browser other then IE can not do DOM manipulation should propably have done horrible things to him/her.
If your format is JSON you can just for-loop them and create the elements and print them. (once you figured out what format your service returns we can help you better.)
I am accustomed to winform TreeView having a Sorted property which automatically manages nodes sorting.
I now have to alphabetically sort an ASP.NET TreeView and I'm surprised I cannot find any similar property or callback method.
Is there any way to automatically achieve this operation in ASP.NET or do I have to manually sort and insert my nodes in correct order?
You'll need to write your own sorting function but its reasonably trivial to add this functionality.
http://blog.mdk-photo.com/post/C-Extentionmethod-Tree-Node-View-Sort().aspx
.NET 3.5 supports extension methods so you can add functionality to pre-existing System Classes. Notice the this syntax on the method parameter. More Info Here
public static void Sort(this TreeView tv)
{
TreeNodeCollection T = tv.Nodes.Sort();
tv.Nodes.Clear();
tv.Nodes.AddRange(T);
}
public static void Sort(this TreeNode tn)
{
TreeNodeCollection T = tn.ChildNodes.Sort();
tn.ChildNodes.Clear();
tn.ChildNodes.AddRange(T);
}
The first link contains the rest of the code you'll need to complete the sorting functionality
Three years later and the TreeView still doesn't support sorting natively. Here's a simple method to do sort all nodes alphabetically.
private void SortTreeNodes(TreeNodeCollection treeNodes)
{
var sorted = true;
foreach (TreeNode treeNode in treeNodes)
{
SortTreeNodes(treeNode.ChildNodes);
}
do
{
sorted = true;
for (var i = 0; i < treeNodes.Count - 1; i++)
{
var treeNode1 = treeNodes[i];
var treeNode2 = treeNodes[i + 1];
if (treeNode1.Text.CompareTo(treeNode2.Text) > 0)
{
treeNodes.RemoveAt(i + 1);
treeNodes.RemoveAt(i);
treeNodes.AddAt(i, treeNode2);
treeNodes.AddAt(i + 1, treeNode1);
sorted = false;
}
}
} while (!sorted);
}
Call it like this
SortTreeNodes(myTreeView.Nodes);