Slickgrid dynamic loading doesn't display (MVC 5) - c#

I have converted my datatable from my controller as such:
public string GetReportResults(int ID)
{
UserInterface engine = new UserInterface();
UserStandardReport rpt = engine.GetStandardReport(CreateLoggedInUser(), ID);
DataTable dt = engine.GetQueryData(CreateLoggedInUser(), rpt);
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
Dictionary<string, object> row;
foreach (DataRow dr in dt.Rows)
{
row = new Dictionary<string, object>();
foreach (DataColumn col in dt.Columns)
row.Add(col.ColumnName, dr[col]);
rows.Add(row);
}
return serializer.Serialize(rows);
}
Returned data snippet:
[{"Customer City":null,"Customer Address Line 1":null,"Customer Address Line 2":null,"Customer Name (Firm or Full Name)":"","Customer State":null,"Customer Zip":null},{"Customer City":null,"Customer Address Line 1":null,"Customer Address Line 2":null,"Customer Name (Firm or Full Name)":"1 Location","Customer State":null,"Customer Zip":null},{"Customer City":null,"Customer Address Line 1":null,"Customer Address Line 2":null,"Customer Name (Firm or Full Name)":"2 location","Customer State":null,"Customer Zip":null},{"Customer City":null,"Customer Address Line 1":null,"Customer Address Line 2":null,"Customer Name (Firm or Full Name)":"3 location","Customer State":null,"Customer Zip":null}]
In my view, I'm using this:
$(function () {
var columnName;
var columns = #Html.Raw(Json.Encode(Model.columns));
for (var n=0; n< columns.length; n++)
{
columnName = columns[n];
cols.push({
id: columnName,
name: columnName,
field: columnName
});
}
$.getJSON("/Home/GetReportResults", {ID: #Model.ID}).done(function(data){
slickdata = data;
});
dataview = new Slick.Data.DataView({inlineFilters: true});
grid = new Slick.Grid("#availableGrid", dataview, cols, options);
dataview.beginUpdate();
dataview.setItems(slickdata);
dataview.endUpdate();
});
My Model.columns is a List that contains the column names {"Customer City","Customer Address Line 1","Customer Address Line 2","Customer Name (Firm or Full Name)","Customer State","Customer Zip"}. These will change based on the results returned.
Currently, I see my columns in the grid, but none of my data is displayed. I've double-checked Firebug. There are no errors. What am I missing for the grid?

Put the call to dataview.setItems(slickdata) inside the $.getJSON() callback.

Related

How to convert string separated by new line and comma to DataTable in C#

I have a string like this:
"Product,Price,Condition
Cd,13,New
Book,9,Used
"
Which is being passed like this:
"Product,Price,Condition\r\Cd,13,New\r\nBook,9,Used"
How could I convert it to DataTable?
Trying to do it with this helper function:
DataTable dataTable = new DataTable();
bool columnsAdded = false;
foreach (string row in data.Split(new string[] { "\r\n" }, StringSplitOptions.None))
{
DataRow dataRow = dataTable.NewRow();
foreach (string cell in row.Split(','))
{
string[] keyValue = cell.Split('~');
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn(keyValue[0]);
dataTable.Columns.Add(dataColumn);
}
dataRow[keyValue[0]] = keyValue[1];
}
columnsAdded = true;
dataTable.Rows.Add(dataRow);
}
return dataTable;
However I don't get that "connecting cells with appropriate columns" part - my cells don't have ~ in string[] keyValue = cell.Split('~'); and I obviously get an IndexOutOfRange at DataColumn dataColumn = new DataColumn(keyValue[0]);
Based on your implementation, I have written the code for you, I have not tested it. But you can use the concept.
DataRow dataRow = dataTable.NewRow();
int i = 0;
foreach (string cell in row.Split(','))
{
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn(cell);
dataTable.Columns.Add(dataColumn);
}
else
{
dataRow[i] = cell;
}
i++;
}
if(columnsAdded)
{
dataTable.Rows.Add(dataRow);
}
columnsAdded = true;
You can do that simply with Linq (and actually there is LinqToCSV on Nuget, maybe you would prefer that):
void Main()
{
string data = #"Product,Price,Condition
Cd,13,New
Book,9,Used
";
var table = ToTable(data);
Form f = new Form();
var dgv = new DataGridView { Dock = DockStyle.Fill, DataSource = table };
f.Controls.Add(dgv);
f.Show();
}
private DataTable ToTable(string CSV)
{
DataTable dataTable = new DataTable();
var lines = CSV.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var colname in lines[0].Split(','))
{
dataTable.Columns.Add(new DataColumn(colname));
}
foreach (var row in lines.Where((r, i) => i > 0))
{
dataTable.Rows.Add(row.Split(','));
}
return dataTable;
}
You can split given string into flattened string array in one call. Then you can iterate through the array and populate list of objects.
That part is optional, since you can immediately populate DataTable but I think it's way easier (more maintainable) to work with strongly-typed objects when dealing with DataTable.
string input = "Product,Price,Condition\r\nCd,13,New\r\nBook,9,Used";
string[] deconstructedInput = input.Split(new string[] { "\r\n", "," }, StringSplitOptions.None);
List<Product> products = new List<Product>();
for (int i = 3; i < deconstructedInput.Length; i += 3)
{
products.Add(new Product
{
Name = deconstructedInput[i],
Price = Decimal.Parse(deconstructedInput[i + 1]),
Condition = deconstructedInput[i + 2]
});
}
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public string Condition { get; set; }
}
So, products collection holds 2 objects which you can easily iterate over and populate your DataTable.
Note: This requires further checks to avoid possible runtime exceptions, also it is not dynamic. That means, if you have differently structured input it won't work.
DataTable dataTable = new DataTable();
dataTable.Columns.Add(new DataColumn(nameof(Product.Name)));
dataTable.Columns.Add(new DataColumn(nameof(Product.Price)));
dataTable.Columns.Add(new DataColumn(nameof(Product.Condition)));
foreach (var product in products)
{
var row = dataTable.NewRow();
row[nameof(Product.Name)] = product.Name;
row[nameof(Product.Price)] = product.Price;
row[nameof(Product.Condition)] = product.Condition;
dataTable.Rows.Add(row);
}

How to fill a DataTable with XElement/XAttribute?

I'm new to C#, I never worked with a DataTable before.
I want a DataGridView with specific names.
DataTable table = new DataTable();
List<string> bla = new List<string>();
XDocument config = XDocument.Load(configFile);
Dictionary<string, string> dict = config.Descendants("Columns").FirstOrDefault().Elements()
.GroupBy(x => (string)x.Attribute("XPath"), y => (string)y.Attribute("Name"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
//I dont know if I need this:
foreach (string key in dict.Keys)
{
table.Columns.Add(key, typeof(string));
}
foreach (XElement position in positions.Where(e => e.HasAttributes))
{
foreach (XAttribute attribute in position.Attributes().Where(a => dict.ContainsKey($"#{a.Name.LocalName}")))
{
string name = attribute.Name.LocalName;
string value = (string)attribute;
string xName = dict["#" + name];
bla.Add(xName);
}
The columns should have the name from xName.
How can I do this?
I've tried this:
foreach (var item in bla)
{
DataRow row = table.NewRow();
row.SetField<string>(item); //this didn't work.
//foreach (string key in dict.Keys)
//{
// row.SetField<string>(key, item[key]);
//}
}
Just want the names from xName as my heading for the output.
Example für xName: Position, Status, Order, Number, ...
As my heading.
And under that the values.
if i understand you correctly, you've got your list of column names ok, but dont know how to create a datatable with the correct column names.
Below is an example of how to add a column and row to a datatable with a specific column header name.
As discussed in the comments, I've demonstrated a process to get the data you need into a structure that allows you to populate your table.
//Class to hold data
public class MyRecordContent
{
public MyRecordContent()
{
//initialise list
RecordsColumns = new List<string>();
}
//Holds a list of strings for each column of the record.
//It starts at position 0 to however many columns you have
public List<string> RecordsColumns { get; set; }
}
//This creates an empty table with the columns
var myTable = new DataTable("Table1");
foreach (var item in bla)
{
if (!myTable.Columns.Contains(item))
{
myTable.Columns.Add(new DataColumn(item, typeof(string)));
}
}
//Here you build up a list of all records and their field content from your xml.
foreach (var xmlNode in yourXMLRecordCollection)
{
var thisRecord = new MyRecordContent();
foreach (var xmlCol in xmlNode.Elements)//Each column value
{
thisRecord.RecordsColumns.Add(xmlCol.GetValue());
}
myListOfRecords.Add(thisRecord);
}
foreach (MyRecordContent record in myListOfRecords)
{
var row = myTable.NewRow();
//Here we set each row column values in the datatable.
//Map each rows column value to be the value in the list at same position.
for (var colPosition = 0; colPosition <= myTable.Columns.Count - 1;) //Number of columns added.
{
row[colPosition] = record.RecordsColumns[colPosition];
}
myTable.Rows.Add(row);
}
In the above, itterate through your list of column names and add each column to the table. You may want to add a switch statement to the loop to change the datatype of the column based upon name if required. Then create of new row off that table and set each fields value accordingly.
Finally, add the new row to the datatable.
Hope that helps.
Then

How to covert a DataTable to Json Format? [duplicate]

This question already has answers here:
Convert datatable to JSON in C#
(18 answers)
Closed 6 years ago.
I am trying to convert the DataTable that I have fetched from the database to Json format. But I am getting an error.
public string ConvertTableToJSON(DataTable objDataTable)
{
ArrayList columnNames = new ArrayList();
int rowCount = objDataTable.Rows.Count;
int currentRow = 1;
string json = "";
//fetching column names
foreach (DataColumn objColumn in objDataTable.Columns)
{
columnNames.Add(objColumn.ColumnName);
}
//generating json string for each row
foreach (DataRow objRow in objDataTable.Rows)
{
json = json + "{";
json = json + ConvertRowToJSON(objRow, columnNames);
json = json + "}";
if (currentRow != rowCount)
{
json = json + ",";
}
currentRow = currentRow + 1;
}
return json;
}
The above is the code for the conversion of the DataTable to Json format.
" Index was outside the bounds of the array. " is the error when debugging the code. This error occurs in the line
if (data[0] == '[' || data[0] == '{')
This method is used to convert datatable to json string
public string ConvertDataTabletoJSON(DataTable dt)
{
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
Dictionary<string, object> row;
foreach (DataRow dr in dt.Rows)
{
row = new Dictionary<string, object>();
foreach (DataColumn col in dt.Columns)
{
row.Add(col.ColumnName, dr[col]);
}
rows.Add(row);
}
return serializer.Serialize(rows);
}
It uses System.Web.Script.Serialization.JavaScriptSerializer to serialize the contents to JSON format:
You can Convert DataTable to JSON using JavaScriptSerializer by using following code
public string DataTableToJsonWithJavaScriptSerializer(DataTable objDataTable)
{
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
List<Dictionary<string, object>> parentRow = new List<Dictionary<string, object>>();
Dictionary<string, object> childRow;
foreach (DataRow row in objDataTable.Rows)
{
childRow = new Dictionary<string, object>();
foreach (DataColumn col in table.Columns)
{
childRow.Add(col.ColumnName, row[col]);
}
parentRow.Add(childRow);
}
return jsSerializer.Serialize(parentRow);
}
You can use Json.Net DLL and convert datatable to json like
public string DataTableToJsonWithJsonNet(DataTable objDataTable)
{
string jsonString=string.Empty;
jsonString = JsonConvert.SerializeObject(objDataTable);
return jsonString;
}
Include library.
Newtonsoft.Json;

Outter joins in LINQ query

This code works good it takes and matches all the unit_no and vehiclename together but it only shows the matches i also need the ones that dont match on.
I am loading a datagrid in WPF with SQLserver data and another Datagrid from oracle data.
private void GetSQLOraclelinqData()
{
var TstarData = GetTrackstarTruckData();
var M5Data = GetM5Data();
DataTable ComTable = new DataTable();
foreach (DataColumn OraColumn in M5Data.Columns)
{
ComTable.Columns.Add(OraColumn.ColumnName, OraColumn.DataType);
}
foreach (DataColumn SQLColumn in TstarData.Columns)
{
if (SQLColumn.ColumnName == "VehicleName")
ComTable.Columns.Add(SQLColumn.ColumnName + "2", SQLColumn.DataType);
else
ComTable.Columns.Add(SQLColumn.ColumnName, SQLColumn.DataType);
}
var results = M5Data.AsEnumerable().Join(TstarData.AsEnumerable(),
a => a.Field<String>("Unit_No"),
b => b.Field<String>("VehicleName"),
(a, b) =>
{
DataRow row = ComTable.NewRow();
row.ItemArray = a.ItemArray.Concat(b.ItemArray).ToArray();
ComTable.Rows.Add(row);
return row;
}).ToList();

Very Big JSON (92,000 rows) does not load

I have a simple function to return my datatable as JSON from c# using the Serializer as follows -
public static string ConvertToJSON (DataTable dt)
{
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
Dictionary<string, object> row;
foreach (DataRow dr in dt.Rows)
{
row = new Dictionary<string, object>();
foreach (DataColumn col in dt.Columns)
{
row.Add(col.ColumnName, dr[col]);
}
rows.Add(row);
}
return serializer.Serialize(rows);
}
Which I use as follows
return ConvertToJSON(objDataTable);
where objDataTable is my Datatable
I also have
return JsonConvert.SerializeObject(strArrMapObject, Formatting.None);
where I am using the library Newtonsoft.Json and strArrMapObject is an Itemarray built from objDataTable
Both the above methods work fine for small datatables and I get the output like this -
["11-06-2014 00:00:00","17:45:00","Beta","357637031475680","404490480844084","78","IN","","8143888569","48"]
But when I do it for a big datatable (eg. 92,000 rows), nothing happens!
There is no response and there is no timeout error also.
So when I use
alert (response);
[in Javascript] or even
document.getElementById('divDataHolder').innerHTML = response;
[in Javascript]
absolutely nothing happens!
Please help!
Rewrite your request so that you can ask
select 100 rows page 1 // selects items 1-100
select 100 rows page 2 // selects items 101-200
This would solve more then 1 problem.
public static string ConvertToJSON (DataTable dt, int page = 0, int count = 100)
//...
foreach (DataRow o in dt.AsEnumerable().Skip(page * count).Take(count))
Edit: You can use following method to get Json
//add reference System.Data
//add reference System.Web.extensions
//add reference System.Web.DataTableExtensions
public static string ConvertToJson(DataTable dt, int page = 0, int count = 100)
{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var rows = new List<Dictionary<string, object>>();
foreach (DataRow dr in dt.AsEnumerable().Skip(page * count).Take(count).ToList())
{
rows.Add(dt.Columns.Cast<DataColumn>().ToDictionary(col => col.ColumnName, col => dr[col]));
}
return serializer.Serialize(rows);
}

Categories