I created a class library and I am trying to add data from a List<string[]> to a DataGridView.
The string is in the format as follows:
"Test, 1^Glucose^10/24/2013 10:00;Test, 2^BUN^10/25/2013 11:00;Test, 3^BUN^10/25/2013 11:00"
I am passing the string from another program. I then an making it into a list and then trying to add it to the DataTable but no such luck. I created the datagridview with four columns.
Selected - Checkbox
Patient Name - String
Order Name - String
Order Date - String
Reason - Combo Box
I am getting an error:
the list is greater than the number of columns.
Note: I can make the string anyway I want before passing to this program so if I need to do something with the string before passing it to the program, please let me know. Is there an easier way?
I just want the data to display and I will work on the rest of it.
Any help would be appreciated.
This is my code:
public partial class RenewOrders : Form
{
public static string strMLMPatientData = string.Empty;
public RenewOrders(string all_patient_data)
{
InitializeComponent();
strMLMPatientData = "Test, 1^Glucose^10/24/2013 10:00;Test, 2^BUN^10/25/2013 11:00;Test, 3^BUN^10/25/2013 11:00"
}
private void RenewOrders_Load(object sender, EventArgs e)
{
this.ConvertStringToList(strMLMPatientData);
}
private void ConvertStringToList(string strMLMPatientData)
{
var patient_list = strMLMPatientData.Split(';').Select(x => x.Split('^')).ToList();
DataTable dtTable = ConvertListToDataTable(patient_list);
dataGridView1.DataSource = dtTable;
}
// Convert to DataTable.
static DataTable ConvertListToDataTable(List<string[]> patient_list)
{
// New table.
DataTable dtTable = new DataTable();
dtTable.Columns.Add("Name", typeof(string));
dtTable.Columns.Add("Order Name", typeof(string));
dtTable.Columns.Add("Order Date/Time", typeof(string));
foreach (var row in patient_list)
{
table.Rows.Add(row);
}
return dtTable;
}
}
First you need to spit the string appropriately to get a list of string arrays. Something like this:
var patient_list = new List<string[]>(strMLMPatientData.Split(';').Select(x => x.Split(',')));
or even better:
var patient_list = strMLMPatientData.Split(';').Select(x => x.Split(',')).ToList();
You need Linq for that, but you get the idea.
Then you need to add columns to your data table. You cant add rows to it when there are no columns..
Try something like this in your function
//add columns appropriately
DataTable table = new DataTable();
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Order", typeof(string));
table.Columns.Add("Date", typeof(string));
foreach (var row in patient_list)
table.Rows.Add(row);
return table;
See an example here. As it stands, your comma separated input string doesnt seem to match your data table column structure. You need to work it out. But I hope you got the idea which way to go.
Related
Is there any way to remove "columns" from an ArrayList?
I got this site up and running before attempting populating my DropDownLists from txt files so I hard-typed each value in. Now I've made an ArrayList from each DropDownList so I can display those lists in DataGridView on the site. The only issue is that "Enabled" and "Selected" show up as columns and I cannot seem to remove the column in the ArrayList, or specify which columns to bring in when creating the ArrayList, or GridView using GridView.Columns.Remove(); because the integers 0 or 1 or 2 don't seem to correspond with anything and the site doesn't run and I can't specify a string as the column title for what to remove.
The DataGrids show up with columns as |Enabled|Selected|Text|Value|
Here's the code for this piece as it stands (You can see what I've tried out and that didn't work that I've commented away):
// Create ListArrays from DropDownLists
ArrayList BuildingList = new ArrayList(Building.Items);
ArrayList DepartmentList = new ArrayList(Department.Items);
//Building.Items.Remove("Enabled");
//Building.Items.Remove("Selected");
// Populate Building GridView
BuildingGrid.DataSource = BuildingList;
BuildingGrid.DataBind();
//BuildingGrid.Columns.Remove;
//BuildingGrid.Columns[0].Visible = false;
// Populate Department GridView
DepartmentGrid.DataSource = DepartmentList;
DepartmentGrid.DataBind();
//DepartmentGrid.Columns[0].Visible = false;
//DepartmentGrid.Columns[1].Visible = false;
I would just go ahead and create a simple 2d array in a txt file with fields for "Value" and "Text" so the DropDownList will pull it in properly, but I can't figure that out either without being terribly inefficient and confusing.
Any help would be appreciated. Thanks.
So, here's the solution I ended up at. I finally figured out how to extract everything from a txt file, and place it into the grid the way I wanted to.
// Populate Department GridView
// get all lines of csv file
string[] BuildingString = File.ReadAllLines(Server.MapPath("Content/BuildingsCSV.csv"));
string[] DepartmentString = File.ReadAllLines(Server.MapPath("Content/DepartmentsCSV.csv"));
// create new datatable
DataTable BuildingTable = new DataTable();
DataTable DepartmentTable = new DataTable();
// Building Table
// get the column header means first line
string[] tempbuild = BuildingString[0].Split(',');
// creates columns of gridview as per the header name
foreach (string t in tempbuild)
{
BuildingTable.Columns.Add(t, typeof(string));
}
// now retrive the record from second line and add it to datatable
for (int i = 1; i < BuildingString.Length; i++)
{
string[] t = BuildingString[i].Split(',');
BuildingTable.Rows.Add(t);
}
// Department Table
// get the column header means first line
string[] tempdept = DepartmentString[0].Split(',');
// creates columns of gridview as per the header name
foreach (string t in tempdept)
{
DepartmentTable.Columns.Add(t, typeof(string));
}
// now retrive the record from second line and add it to datatable
for (int i = 1; i < DepartmentString.Length; i++)
{
string[] t = DepartmentString[i].Split(',');
DepartmentTable.Rows.Add(t);
}
// assign gridview datasource property by datatable
BuildingGrid.DataSource = BuildingTable;
BuildingGrid.DataBind();
BuildingGrid.Rows[0].Visible = false;
DepartmentGrid.DataSource = DepartmentTable;
DepartmentGrid.DataBind();
DepartmentGrid.Rows[0].Visible = false;
foreach (DataRow drb in BuildingTable.Rows)
{
BuildingDrop.Items.Add(new ListItem(drb[0].ToString(), drb[1].ToString()));
}
foreach (DataRow drd in DepartmentTable.Rows)
{
DepartmentDrop.Items.Add(new ListItem(drd[0].ToString(), drd[1].ToString()));
}
Hello sir i am not native english, new here in stackoverflow and new in programming but i will try my best to share my problem with you:
I added some comments in my code so i hope you can better see what the problems are
i am trying to make something like a temporary datatable that gets informations (only the rows matter) from 1 specific datatable(there will be more see in the code) and the "temporarydatatable" gives these to a list<> i tried it with linq. ofc i have my own mind and tried to change it a way i understand (LINQ query on a DataTable this wasnt really helpful for me :X ) and i tried some other things as well but i dont want to smash 10 links here :P
so here comes the code:
public MainWindow()
{
InitializeComponent();
datatable1();
}
public void datatable1()
{
/*This Table should get the informations from datatable_1 or
another one (there will be some more tables and the viewtable will
get the informations from the table where the
Type ==(i guess it will be a combobox) selected Type */
DataTable viewtable = new DataTable();
viewtable.Columns.Add("Typ", typeof(string));
viewtable.Columns.Add("Name", typeof(string));
viewtable.Columns.Add("Anzahl", typeof(string));
viewtable.Columns.Add("Zeit", typeof(string));
/*here is the main problem i have*/
viewtable.Rows =from _Row1 in datatable_1 where "Typ" =="Una";
/*it "worked" like this so i get the informations in my list*/
viewtable.Rows.Add("Una", "Testschrank2", "9000", "0:20:30");
//this table is a example table holding the informations
DataTable datatable_1 = new DataTable();
datatable_1.Clear();
datatable_1.Columns.Add("Typ");
datatable_1.Columns.Add("Name");
datatable_1.Columns.Add("Anzahl");
datatable_1.Columns.Add("Zeit");
DataRow _Row1 = datatable_1.NewRow();
datatable_1.Rows.Add("Una", "Testschrank2", "9000", "0:20:30");
// _Row1["Zeit"] = (4, 30, 0);
datatable_1.Rows.Add(_Row1);`
}
well i guess i added too much code but like i said i am really new to this so its a bit difficult for me to point on my problem with little code excuse me sir
and
thanks for your help o/
To get the value from the first DataTable you have to pull all DataRows from it as Lei Yang suggested in his comment.
DataRow temp = datatable_1.Rows.OfType<DataRow>()
.SingleOrDefault(x=>x["Typ"].ToString() == "Una");
1: You cannot assign to the property Rows since it is readonly.
2: You cannot just use simply viewtable.Rows.Add(temp) because this row already belongs to another table. This will result in a System.ArgumentException
So you need to import the row:
if (temp != null)
{
viewtable.ImportRow(temp);
}
EDIT:
If you intend to capture more than one row using the where clause you can use a List<DataRow> to save them temporarily and import each row afterwards in a loop:
List<DataRow> temp = datatable_1.Rows.OfType<DataRow>()
.Where(x => x["Typ"].ToString() == "Una").ToList();
if (temp.Count > 0)
{
foreach (var row in temp)
{
viewtable.ImportRow(row);
}
}
EDIT 2:
Here are some sources for further research:
How to: Locate a Specific Row in a DataTable
In this example you can use also the Select method to get the desired rows. This would look like this:
DataRow [] temp2 = datatable_1.Select("Typ ='Una'", "Name DESC", DataViewRowState.Added);
// or the short version:
DataRow [] temp2 = datatable_1.Select("Typ ='Una'");
the outcome will be the same. This version is from a an answer to a similar question.
I'm currently stuck when trying to implement the sorting feature of the Kendo Grid control. When I click a column to sort the values, it takes me to a 404 page. None of the documentation I've looked at is binding the grid to a DataTable and I'm also wondering if there needs to be a specific action for the sorting. Can anyone help?
View Code:
#{
if (IsPost && Request.Url.AbsolutePath.Contains("Carriers"))
{
#(Html.Kendo().Grid((DataTable)(ViewData["CarrierResults"]))
.Name("carrierSearchResults")
.Sortable()
)
}
}
Controller Code:
[HttpPost]
public ActionResult Carriers()
{
DealerPortalRepository dpr = new DealerPortalRepository();
// The SearchForCarriers method below returns a DataTable
ViewData["CarrierResults"] = dpr.SearchForCarriers();
return View("~/Views/Search/Index.cshtml");
}
Edit: Query code:
public DataTable SearchForCarriers()
{
var query = from a in db.Affiliates
where a.AffiliateLevel == 1
select new { a.AffiliateName };
return createCarrierTable(query);
}
public DataTable createCarrierTable(IEnumerable<dynamic> query)
{
// Create new DataTable since the query above does not produce a DataRow that follows a schema already defined in the database.
DataTable dt = new DataTable();
dt.Columns.Add(
new DataColumn()
{
DataType = System.Type.GetType("System.String"),
ColumnName = "Affiliate Name"
}
);
// Add the row(s) to the DataTable.
foreach (dynamic item in query)
{
var row = dt.NewRow();
row["Affiliate Name"] = item.AffiliateName;
dt.Rows.Add(row);
}
return dt;
}
P.S. I know I should probably be using a model instead of ViewData, but I didn't originally implement it that way because the anonymous type in my DataTable was throwing me off.
Since I cannot see the rest of your code, here is my guess.
Can you remove [HttpPost] and test it again?
If still doesn't work, you need another action method which accepts DataSourceRequest as parameter.
public ActionResult Carriers_Read([DataSourceRequest]DataSourceRequest request)
{
...
}
Look at Grid Ajax Binding.
I have DataGridView and I set DataSource of datagridview by using DataTables.
DataTable dt = new DataTable();
dt.Columns.Add("Image",typeof(Bitmap));
dt.Columns.Add("Col2", typeof(string));
dt.Columns.Add("Col3", typeof(string));
dt.Columns.Add("Col4", typeof(string));
dt.Columns.Add("Col5", typeof(string));
int currentrow = 0;
foreach (Dev d in Devs)
{
dt.Rows.Add(dt.NewRow());
Bitmap bmp = Test(d);
dt.Rows[currentrow][0] = bmp;
dt.Rows[currentrow][1] = d .ID;
dt.Rows[currentrow][2] = d .Name;
dt.Rows[currentrow][3] = d .Country;
dt.Rows[currentrow][4] = d .State;
currentrow++;
}
datagridview.DataSource = dt;
This code sort when my column type of string, but i want to sort based on image also. I want to click on image column and it should sort based on images. There are three types of image only, so i want same image should be together for easier display purpose.
I searched on but could not find any solution yet.
Any thing that can guide me to right direction?
Got Error when i Tried something like this
datagridview.Sort(dgvFusePTW.Columns[0], ListSortDirection.Ascending);
Error : Data-bound DataGridView control can only be sorted on data-bound columns.
UPDATE :
I added one more column. It is hidden, when use click on Image column (1st one), it fires ColumnHeaderMouseClick events. Added Logic there to sort hidden column.
It is just work around which one clicked for me.
Thanks you,
L.E.
You need to use a DataView if you want to do that. (You will need to use DataSetExtensions to leverage the LINQ.)
// the Bitmap class has the RawFormat property that tells whether
// it's JPG, PNG, BMP, etc etc
DataView dv = dt.AsEnumerable()
.OrderBy(c => c.Field<Bitmap>("Image").GetImageOrder()) // sort by image type
.ThenBy(d => d.Field<string>("Col2")) // then sort by ID...
.AsDataView();
// take the dataview and bind...
datagridview.DataSource = dv;
You also need to define the following static extension method:
public static class ImageHelper
{
private static ImageFormat[] supportedFormats = new ImageFormat[]
{
ImageFormat.Bmp,
ImageFormat.Gif,
ImageFormat.Jpeg,
ImageFormat.Png,
ImageFormat.Tiff,
ImageFormat.Wmf,
ImageFormat.Emf,
ImageFormat.Exif
};
public static int GetImageOrder(this Image target)
{
for (int i = 0; i < supportedFormats.Length; i++)
{
if (target.RawFormat.Equals(supportedFormats[i]))
{
return i;
}
}
// the image format is not within our supported formats array:
// just order it to the very end
return 9999;
}
}
Note that the supportedFormats array has an arbitrary sort order that I just thought up -- you can reorder the array any way you want and the images should reorder as you wish.
How to do following scenario:
I have some DataTable which contains for example some rows:
1.rowa
2.rowab
3.row
4.rowaba
...
n. rowabba
How to sort rows by lenght, not by name. I wan to to sort Table by length of fields.
You could add an extra column to your DataTable, supplying an expression containing a call to the len() function, causing the column's values to be automatically computed:
table.Columns.Add("LengthOfName", typeof(int), "len(Name)");
Then you can simply sort on your new column before binding the DataTable to a grid to whatever kind of UI control you plan to use:
table.DefaultView.Sort = "LengthOfName";
If you must use DataTable, you could introduce an extra column for the sort. In this case, you could set the value in the column simply to the length of each desired cell, and then sort by the new column:
DataTable table = new DataTable();
DataColumn val = table.Columns.Add("Value", typeof(string));
table.Rows.Add("abc");
table.Rows.Add("defgh");
table.Rows.Add("i");
table.Rows.Add("jklm");
// sort logic: ***** schou-rode's "len(...)" approach is better *****
DataColumn sort = table.Columns.Add("Sort", typeof(int));
foreach (DataRow row in table.Rows) {
row[sort] = ((string)row[val]).Length;
}
DataView view = new DataView(table);
view.Sort = "Sort";
foreach (DataRowView row in view) {
Console.WriteLine(row.Row[val]);
}
Personally, I'd use a typed list - of either a class, or a string in this case (since you only list one value):
List<string> list = new List<string> {
"abc", "defgh", "i", "jklm"};
list.Sort((x, y) => x.Length.CompareTo(y.Length));
foreach (string s in list) {
Console.WriteLine(s);
}