I want to add a stored CustomDataGridViewRow into a DataGridView which is binded. Like follows:
CustomDataGridViewRow rowTemplate = new CustomDataGridViewRow();
dataGridView1.RowTemplate = rowTemplate;
Datenbank.cmd =
new SqlCommand("[Terminauswertung_Bericht_Gesamt]", Datenbank.connection);
Datenbank.cmd.CommandType = CommandType.StoredProcedure;
Datenbank.cmd.Parameters.AddWithValue("#berichtsnr", 1);
SqlDataAdapter adapter = new SqlDataAdapter(Datenbank.cmd);
dataSet1.Tables.Clear();
adapter.Fill(dataSet1, "Table");
bs = new BindingSource();
bs.DataSource = dataSet1.Tables["Table"];
dataGridView1.DataSource = bs;
Thought it goes this way:
dataSet1.Tables[0].Rows.Add(Cache.getRow(1));
public class cache
{
Dictionary<int, CustomDataGridViewRow> _cache =
new Dictionary<int, CustomDataGridViewRow>();
public CustomDataGridViewRow getRow(int index)
{
foreach (KeyValuePair<int, CustomDataGridViewRow> dic in _cache)
{
if (dic.Key == index)
return (dic.Value);
}
return (new CustomDataGridViewRow());
}
}
But it only shows me DataGridViewRow { Index=1 } in first cell.
solved it
DataRow newRow =test.Tables[0].NewRow();
newRow.ItemArray = Cache.getRowValues(child);
test.Tables[0].Rows.InsertAt(newRow, c.Index+1);
public string[] getRowValues(int index)
{
List<string> temp = new List<string>();
foreach (KeyValuePair<int, CustomDataGridViewRow> dic in _cache)
{
if (dic.Key == index)
{
foreach (DataGridViewCell cell in dic.Value.Cells)
temp.Add(cell.Value.ToString());
}
}
string[] result = temp.ToArray();
return (result);
}
Related
I am working with WindowsForm and C# and I am filling out a List<> and everything is fine so far
In my list<> I have 103 records but when I pass to my DataTable no record appears only the headers, that is to say that when I receive my table everything shows in null
The truth is, I'm a little new to this and it's the first one that I'm working on.
List<MSProject.Task> tasks = new List<MSProject.Task>();
DataTable Tabla = new DataTable();
Tabla = ListToDataTable(tasks);
my code
public static DataTable ListToDataTable<T>(IList<T> data)
{
DataTable table = new DataTable();
//special handling for value types and string
if (typeof(T).IsValueType || typeof(T).Equals(typeof(string)))
{
DataColumn dc = new DataColumn("Value");
table.Columns.Add(dc);
foreach (T item in data)
{
DataRow dr = table.NewRow();
dr[0] = item;
table.Rows.Add(dr);
}
}
else
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
foreach (PropertyDescriptor prop in properties)
{
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
{
try
{
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
}
catch (Exception ex)
{
row[prop.Name] = DBNull.Value;
}
}
table.Rows.Add(row);
}
}
return table;
}
Thanks in advance
I've run your code and it's work, The problem I believe is that the MSProject.Task doesn't have any public properties and you are iterating only in properties. PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
see the code below:
//with properties
public class MSProject.Task
{
public string Name {get; set;}
public string code {get; set;}
}
//no properties
public class MSProject.Task2
{
public string Name;
public string code;
}
private void ShowRownsInGrid()
{
//it works shows rows in DataGridView!
List<MSProject.Task> tasks = new List<MSProject.Task>()
{
new MSProject.Task(){ Name = "Joao", code = "01215452124"},
new MSProject.Task(){ Name = "Maria", code = "4564678"},
};
DataTable Tabla = new DataTable();
Tabla = ListToDataTable(tasks);
MessageBox.Show(Tabla.Rows.Count.ToString()); //Show '2'
dataGridView1.DataSource = Tabla; //Show 2 rows
}
private void DontShowRownsInGrid()
{
//it doesn't work, no rows are displayed in the DataGridView!
List<MSProject.Task2> tasks = new List<MSProject.Task2>()
{
new MSProject.Task2(){ Name = "Joao", code = "01215452124"},
new MSProject.Task2(){ Name = "Maria", code = "4564678"},
};
DataTable Tabla = new DataTable();
Tabla = ListToDataTable(tasks);
MessageBox.Show(Tabla.Rows.Count.ToString()); //Show '2'
dataGridView1.DataSource = Tabla; //does not show lines
}
I need to create a DataTable from another DataTable that I have but with only some columns (exactly same rows).
Is there an easy way to do this using LINQ?
I tried:
DataTable dataCopy = dt.AsEnumerable()
.Select(r => new { A = r.Field<string>("Column A"),
B = r.Field<string>("Column B") });
But it doesn't have a "CopyToDataTable" method.
I'm looking for the best performance way to do this because my "source" DataTable is huge!
You can simply copy the dataTable using dataTable.Copy() and remove the unwanted columns from the copied object.
var dt1 = dt.Copy();
dt.Columns.Remove("<columnsToRemove>")
Stopwatch time = new Stopwatch();
time.Start();
//COMPARE YOUR CODE (.Copy, Clone or Develop yourself)
DataTable dtTarget = dtSource.CopyDataTable(new List<string>() { "A", "B" });
foreach (DataColumn column in dtTarget.Columns)
{
Console.WriteLine("ColumnName : {0}", column.ColumnName);
foreach (DataRow row in dtTarget.Rows)
{
Console.WriteLine("Rows : {0}", row[column.ColumnName]);
}
}
time.Stop();
Console.WriteLine("{0}", time.Elapsed);
public static class DataTableHelper
{
public static DataTable CopyDataTable(
this DataTable dtSource,
List<string> columnsName)
{
DataTable dtTarget = new DataTable();
if (dtSource.Columns.Count > 0)
{
foreach (DataColumn columnSource in dtSource.Columns)
{
var columnTargetMapped = columnsName.FirstOrDefault(c => c == columnSource.ColumnName);
if(columnTargetMapped == null)
{
continue;
}
dtTarget.Columns.Add(columnTargetMapped);
foreach (DataRow drSource in dtSource.Rows)
{
var valueColumn = drSource[columnSource];
DataRow drTarget = dtTarget.NewRow();
drTarget[columnTargetMapped] = valueColumn;
dtTarget.Rows.Add(drTarget);
}
}
}
return dtTarget;
}
public static DataTable GetDataTablePart(this DataTable dt, params string[] ColumnNames)
{
var dtPart = new DataTable("TablePart");
var Names = new List<DataColumn>();
foreach (DataColumn Column in dt.Columns)
{
if(ColumnNames.Contains(Column.ColumnName))
{
Names.Add(Column);
}
}
dtPart.Columns.AddRange(Names.ToArray());
foreach(DataRow row in dt.Rows)
{
var NewRow = new object[Names.Count()];
var i = 0;
foreach (var Name in Names)
{
NewRow[i] = row[Name];
i = i + 1;
}
dtPart.LoadDataRow(NewRow, false);
}
return dtPart;
}
linq version....
public static DataTable GetDataTablePart(this DataTable dt, params string[] ColumnNames)
{
var RowCount = 0;
var dtPart = new DataTable("TablePart");
dtPart.Columns.AddRange((from column in dt.Columns.Cast<DataColumn>()
where ColumnNames.Contains(column.ColumnName)
select column).ToArray());
return (from row in dt.AsEnumerable()
let rowCount = RowCount = dt.Rows.Count
let RowValues = (from column in dtPart.Columns.Cast<DataColumn>()
select row[column]).ToArray()
let decCount = RowCount = RowCount - 1
where dtPart.LoadDataRow(RowValues,LoadOption.OverwriteChanges) != default && decCount > 0
select dtPart).FirstOrDefault();
}
I have data like
ConcurrentDictionary<string, ConcurrentDictionary<string,string> OneTwoThree =
new ConcurrentDictionary<string, ConcurrentDictionary<string, string>();
I want a result like this Final Image
What I tried:
DataTable dt = new DataTable();
dt.Columns.Add("TwoDetails");
ISet<string> two = new HashSet<string>();
Parallel.ForEach(OneTwoThree , One=>
{
dt.Columns.Add(One.Key);
foreach(var Two in One.Value)
{
two.Add(Two.Key); // To get Distinct Values
}
});
foreach(var item in two)
{
var row = dt.NewRow();
row["TwoDetails"] = row;
}
Now I don't have the idea to append "Three-Values" to a particular cell, as shown in the image.
Any Suggestions.
Another pivot table question. Done a 1000. See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication31
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, Dictionary<string, string>> OneTwoThree = new Dictionary<string, Dictionary<string, string>>() {
{"A", new Dictionary<string,string>(){{"U","s"}, {"Z","a"}}},
{"B", new Dictionary<string,string>(){{"W","e"},{"X","d"},{"Y","d"}}},
{"C", new Dictionary<string,string>(){{"V","f"}, {"W","a"},{"Z","w"}}},
};
string[] columns = OneTwoThree.Select(x => x.Key).OrderBy(x => x).ToArray();
DataTable dt = new DataTable();
dt.Columns.Add("TwoDetails", typeof(string));
foreach(string column in columns)
{
dt.Columns.Add(column, typeof(string));
}
string[] rows = OneTwoThree.Select(x => x.Value.Select(y => y.Key)).SelectMany(x => x).Distinct().OrderBy(x => x).ToArray();
var flip = rows.Select(x => new { row = x, columns = OneTwoThree.Where(y => y.Value.ContainsKey(x)).Select(y => new { col = y.Key, value = y.Value[x] }).ToList() }).ToList();
//create pivot table
foreach (var row in flip)
{
DataRow newRow = dt.Rows.Add();
newRow["TwoDetails"] = row.row;
foreach (var column in row.columns)
{
newRow[column.col] = column.value;
}
}
}
}
}
You can not access the data table rows with their names but using row numbers you can find a particular row in the data table.So for that, You need to create one class like
public class DataTableDetails
{
public string RowName { get; set; }
public int RowNumber { get; set; }
}
And this is not effecient solution, but can help you
ISet<string> two = new HashSet<string>();
List<DataTableDetails> dtdetaills=new List<DataTableDetails>();
Parallel.ForEach(OneTwoThree , One=>
{
dt.Columns.Add(One.Key);
foreach(var Two in One.Value)
{
two.Add(Two.Key); // To get Distinct Values
}
});
int count=0;
foreach(var item in two)
{
var row = dt.NewRow();
row["TwoDetails"] = row;
DataTableDetails details = new DataTableDetails();
details.RowName = item;
details.RowNumber = count++; // we can easily get row number
dtdetails.Add(details);
}
And Finally
foreach(var One in OnrTwoThree)
{
foreach(var Two in One.Value)
{
foreach(var rowdetails in dtdetails)
{
if(Two.Key==rowdetails.RowName)
{
dt.Rows[rowdetails.RowNumber][One.Key] = Two.Value;
}
}
}
}
am searching and cracking my brain on how to convert a dynamic list to a databale,
c#, please advise, thanks
List<dynamic>dlist=new List<dynamic>
to
DataTable
I think you looking something like this. Hope it's working for you.
From dynamic list to DataTable:
List<dynamic> dlist=new List<dynamic>
var json = JsonConvert.SerializeObject(dlist);
DataTable dataTable = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
Also to get JsonString from DataTable:
string JSONresult = JsonConvert.SerializeObject(dataTable);
The following is the method through which you can convert any list object to datatable..
public DataTable ConvertToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
http://social.msdn.microsoft.com/Forums/vstudio/en-US/6ffcb247-77fb-40b4-bcba-08ba377ab9db/converting-a-list-to-datatable?forum=csharpgeneral
public DataTable ToDataTable<T>(dynamic items)
{
DataTable dtDataTable = new DataTable();
if (items.Count == 0) return dtDataTable;
((IEnumerable)items[0]).Cast<dynamic>().Select(p => p.Name).ToList().ForEach(col => { dtDataTable.Columns.Add(col); });
((IEnumerable)items).Cast<dynamic>().ToList().
ForEach(data =>
{
DataRow dr = dtDataTable.NewRow();
((IEnumerable)data).Cast<dynamic>().ToList().ForEach(Col => { dr[Col.Name] = Col.Value; });
dtDataTable.Rows.Add(dr);
});
return dtDataTable;
}
I don't know why you need this, however, you can use this ObjectShredder using reflection which can convert anything to DataTable, so even dynamic or anonymous types:
Implement CopyToDataTable<T> Where the generic Type T Is Not a DataRow
However, my suggestion is to not name that extension method CopyToDataTable but for example CopyAnyToDataTable to avoid conflicts with the existing extension method CopyToDataTable.
Use this function ,
public static DataTable ConvertToDatatable<T>(this IList<T> data)
{
PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
for(int i = 0 ; i < props.Count ; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, prop.PropertyType);
}
object[] values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = props[i].GetValue(item);
}
table.Rows.Add(values);
}
return table;
}
If the underlying type is ExpandoObject, then you need to check for IDictionary instead of going via reflection. Hopefully this helps someone else in the future:
public static DataTable ConvertToDataTable<T>(IEnumerable<T> data)
{
DataTable table = new DataTable();
foreach (T item in data)
{
if (item is IDictionary<string, object> dict)
{
foreach (var key in dict)
{
table.Columns.Add(key.Key, key.Value?.GetType() ?? typeof(object));
}
break;
}
foreach (var prop in typeof(T).GetProperties())
{
table.Columns.Add(prop.Name, prop.PropertyType);
}
break;
}
DataRow row = null;
foreach (T item in data)
{
if (item is IDictionary<string, object> dict)
{
row = table.NewRow();
foreach (var key in dict)
{
row[key.Key] = key.Value;
}
table.Rows.Add(row);
continue;
}
row = table.NewRow();
foreach (var prop in typeof(T).GetProperties())
{
row[prop.Name] = prop.GetValue(item);
}
table.Rows.Add(row);
}
return table;
}
To Convert the Dynamic List object into DataTable using C#
public DataTable DynamicToDT(List<object> objects)
{
DataTable dt = new DataTable("StudyRecords"); // Runtime Datatable
string[] arr = { "Name", "Department", "CollegeName", "Address" };// Column Name for DataTable
if (objects != null && objects.Count > 0)
{
for (int i = 0; i < objects.Count; i++)
{
dt.Columns.Add(arr[i]);
if (i == 0)
{
var items = objects[0] as IEnumerable<string>;
foreach (var itm in items)
{
DataRow dr1 = dt.NewRow(); // Adding values to Datatable
dr1[arr[i]] = itm;
dt.Rows.Add(dr1);
}
}
else
{
var items = objects[i] as IEnumerable<string>;
int count = 0;
foreach (var itm in items)
{
dt.Rows[count][arr[i]] = itm;
count++;
}
}
}
return dt; // Converted Dynamic list to Datatable
}
return null;
}
public static DataTable DynamicToDT(List objects)
{
var data = objects.ToArray();
if (data.Count() == 0) return null;
var dt = new DataTable();
foreach (var key in ((IDictionary<string, object>)data[0]).Keys)
{
dt.Columns.Add(key);
}
foreach (var d in data)
{
dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
}
return dt;
}
// Obtem a lista dinamica via chamada API
List<dynamic> resultado = ExecutaQuery(sql);
// converte a lista dinamica com o resultado em JSON
string json = JsonConvert.SerializeObject(resultado);
// converte o json em datatable
DataTable dataTable = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
Currently we are doing this by looping through each value of list and dictionary:
private DataTable ChangeToDictionary(List<Dictionary<string,int>> list)
{
DataTable datatTableReturn = new DataTable();
if (list.Count() > 0)
{
Dictionary<string, int> haeders = list.ElementAt(0);
foreach (var colHead in haeders)
{
datatTableReturn.Columns.Add(colHead.Key);
}
}
foreach (var row in list)
{
DataRow dataRow = datatTableReturn.NewRow();
foreach (var col in row)
{
dataRow[col.Key] = col.Value;
}
datatTableReturn.Rows.Add(dataRow);
}
return datatTableReturn;
}
But is there a better way? Looping through so many times doesn't feel good
The answers above don't address the issue of the dictionary having more than 1 row. This solution addresses the issue.
static DataTable ToDataTable(List<Dictionary<string, int>> list)
{
DataTable result = new DataTable();
if (list.Count == 0)
return result;
var columnNames = list.SelectMany(dict=>dict.Keys).Distinct();
result.Columns.AddRange(columnNames.Select(c=>new DataColumn(c)).ToArray());
foreach (Dictionary<string,int> item in list)
{
var row = result.NewRow();
foreach (var key in item.Keys)
{
row[key] = item[key];
}
result.Rows.Add(row);
}
return result;
}
static void Main(string[] args)
{
List<Dictionary<string, int>> it = new List<Dictionary<string, int>>();
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("a", 1);
dict.Add("b", 2);
dict.Add("c", 3);
it.Add(dict);
dict = new Dictionary<string, int>();
dict.Add("bob", 34);
dict.Add("tom", 37);
it.Add(dict);
dict = new Dictionary<string, int>();
dict.Add("Yip Yip", 8);
dict.Add("Yap Yap", 9);
it.Add(dict);
DataTable table = ToDictionary(it);
foreach (DataColumn col in table.Columns)
Console.Write("{0}\t", col.ColumnName);
Console.WriteLine();
foreach (DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
Console.Write("{0}\t", row[column].ToString());
Console.WriteLine();
}
Console.ReadLine();
}
And the output looks like...
a b c bob tom Yip Yip Yap Yap
1 2 3
34 37
8 9
Speed, elegance and reusability don't go together. You always choose more important one, and try to balance other two.
Faster the code, uglier it is.
Prettier it is, less reusable it is.
Here's an example of "elegant" solution, but that goes with it not being very readable.
private static DataTable ToDictionary(List<Dictionary<string, int>> list)
{
DataTable result = new DataTable();
if (list.Count == 0)
return result;
result.Columns.AddRange(
list.First().Select(r => new DataColumn(r.Key)).ToArray()
);
list.ForEach(r => result.Rows.Add(r.Select(c => c.Value).Cast<object>().ToArray()));
return result;
}
Try this
List<Dictionary<string, object>> ListDic;
var stringListDic = JsonConvert.SerializeObject(ListDic);
var dataTable = JsonConvert.DeserializeObject<DataTable>(stringListDic);
Try this:
private DataTable GetDataTableFromDictionaries<T>(List<Dictionary<string, T>> list)
{
DataTable dataTable = new DataTable();
if (list == null || !list.Any()) return dataTable;
foreach (var column in list.First().Select(c => new DataColumn(c.Key, typeof(T))))
{
dataTable.Columns.Add(column);
}
foreach (var row in list.Select(
r =>
{
var dataRow = dataTable.NewRow();
r.ToList().ForEach(c => dataRow.SetField(c.Key, c.Value));
return dataRow;
}))
{
dataTable.Rows.Add(row);
}
return dataTable;
}
How about something like the code below?
Good, because it iterates each row exactly once. It should be pretty quick, I've included obvious exceptions to make the code safer.
private static DataTable DictionariesToDataTable<T>(
IEnumerable<IDictionary<string, T>> source)
{
if (source == null)
{
return null;
}
var result = new DataTable();
using (var e = source.GetEnumerator())
{
if (!e.MoveNext())
{
return result;
}
if (e.Current.Keys.Length == 0)
{
throw new InvalidOperationException();
}
var length = e.Current.Keys.Length;
result.Columns.AddRange(
e.Current.Keys.Select(k => new DataColumn(k, typeof(T))).ToArray());
do
{
if (e.Current.Values.Length != length)
{
throw new InvalidOperationException();
}
result.Rows.Add(e.Current.Values);
}
while (e.MoveNext());
return result;
}
}
try my solution, seems very clean to me:
private DataTable DictonarysToDataTable(List<Dictionary<string, int>> list)
{
DataTable table = new DataTable();
foreach (Dictionary<string,string> dict in list) //for every dictonary in the list ..
{
foreach (KeyValuePair<string,int> entry in dict) //for every entry in every dict
{
if (!myTable.Columns.Contains(entry.Key.ToString()))//if it doesn't exist yet
{
myTable.Columns.Add(entry.Key); //add all it's keys as columns to the table
}
}
table.Rows.Add(dict.Values.ToArray()); //add the the Values of every dict in the list as a new row
}
return table;
}
Edit:
Oh Snap, this works only for one Dictionary .. i didn't think it through.
But maybie you can modify it to work for a List of Dictionarys ..
Give this a try please
DataTable table = new DataTable();
foreach (IDictionary<string, object> row in DeviceTypeReport)
{
foreach (KeyValuePair<string, object> entry in row)
{
if (!table.Columns.Contains(entry.Key.ToString()))
{
table.Columns.Add(entry.Key);
}
}
table.Rows.Add(row.Values.ToArray());
}
private DataTable toDataTable(List<RetirementDiskModelDto> retirementDiskModelDtos)
{
DataTable result = new DataTable();
foreach (var col in retirementDiskModelDtos.FirstOrDefault().Items)
result.Columns.Add(col.Key);
foreach (var row in retirementDiskModelDtos)
{
DataRow newrow = result.NewRow();
foreach (var col in retirementDiskModelDtos.FirstOrDefault().Items)
newrow[col.Key] = col.Value;
result.Rows.Add(newrow);
}
return result;
}