I am confused on DataTable.DefaultView.Sort. Here is the segment of the code I want to use it in.
actionLogDT.DefaultView.Sort = "StartDate";
foreach (CustomerService.ActionLogStartEndRow logRow in actionLogDT)
{
// code here
}
The samples I have seen don't use the foreach loop and thus is confusing me on how to process this. It isn't sorting as I thought it should be.
I see that .DefaultView returns a view, and .Table gives a compile error.
actionLogDT.DefaultView.Sort = "StartDate";
actionLogDT = actionLogDT.DefaultView.ToTable();
Sorting the view won't change the sort order of the data in the table, just the order in the view. It should work if you do your foreach on the view instead, casting the row from the DataRowView back to your strongly typed row.
foreach (DataRowView logRowView in actionLogDT.DefaultView)
{
CustomerService.ActionLogStartEndRow logRow = logRowView.Row as CustomerService.ActionLogStartEndRow;
// code here
}
I had to take a slightly different approach. This post was the closest I could find to get my code to work. Here is the working result:
actionLogDT.DefaultView.Sort = "StartDate";
DataView dv = actionLogDT.DefaultView;
foreach (DataRowView logRow in dv) { . . . }
From there I just have to cast the value back into it's proper type.
(string)logRow["Status"].ToString()
foreach (var logRow in actionLogDT.DefaultView.ToDataTable()) { ... }
Additionally, Since it seemed like you wanted to loop through records, you can just loop through the dataRowView objects in the DefaultView.
foreach (DataRowView drv in table.DefaultView)
{
string strValue = drv["ColumnName"].ToString();
// its also worth mentioning that a DataRowView has a Row
strValue = drv.Row["ColumnName"].ToString();
}
Please try this:
actionLogDT.DefaultView.Sort = "["+actionLogDT.Columns[0].ColumnName+"] asc";
Just curious: Why are you using the DataRowView?
i.e.
foreach (DataRow row in actionLogDT.Rows)
{
Console.WriteLine(row["Status"]);
}
If you need a datatable back then you can do something like:
var dv = actionLogDT.DefaultView;
dv.Sort = "StartDate";
actionLogDT = dv.ToTable();
In VB.NET, the code below was the best way for me to invoke the solution. Just copy your origtable to a DataView, and then the dataview can be sorted with a simple .sort command, and then set a new table equal to the sorted view (of your original table). Use the sorted table dt for your processing thereafter.
Dim View1 As DataView = New DataView(origtable)
View1.Sort = "LastName"
Dim dt As DataTable = View1.ToTable
Related
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.
How to loop all data in checkedlistbox in 'PROPER' way and print it on console or pop up on messagebox one by one?
I populated my clbPackages this way
// clbPackages is a checkedlistbox
SqlCommand scPackages = new SqlCommand("SELECT XXX FROM XXX", sqlConnection);
SqlDataReader readerPackages;
readerPackages = scPackages.ExecuteReader();
DataTable dtPackages = new DataTable();
dtPackages.Columns.Add("PACKAGE_GROUP_ID", typeof(string));
dtPackages.Columns.Add("PACKAGE_GROUP_NAME", typeof(string));
dtPackages.Load(readerPackages);
this.clbPackages.DataSource = dtPackages;
this.clbPackages.ValueMember = "PACKAGE_GROUP_ID";
this.clbPackages.DisplayMember = "PACKAGE_GROUP_NAME";
Now I have to loop that checkedlistbox because I am trying to check some in, my best try is this code below
foreach (var item in clbPackages.Items)
{
MessageBox.Show(item.ToString());
}
It only return xxx.xxx.DataRowView, and if I try to loop again the item it will show error "foreach statement cannot operate on variables of type 'object' because 'object' "
answered by Bjorn
other way to deal
foreach (object item in clbPackages.Items)
{
DataRowView castedItem = item as DataRowView;
string groupId= castedItem["PACKAGE_GROUP_ID"].ToString();
MessageBox.Show(groupId);
}
Sounds like the objects in the Items-collection is of type DataRowView. So if you convert each item to a DataRowView and get the value from that object you should be fine:
foreach (DataRowView item in clbPackages.Items)
{
MessageBox.Show(item["PACKAGE_GROUP_NAME"].ToString());
}
As far as I see you have access to your original data in original:
this.clbPackages.DataSource = dtPackages;
So all you have to do is to convert your DataSource to the original items (cast it to DataTable) and you can use all original data, isn't it?
To loop all data in a checkedListBox control try with this.
for(int i=0; i<clbPackages.Items.Count ; i++)
{
MessageBox.Show(clbPackages.Items[i].ToString());
}
I have a datatable DTgraph, that datatable has a column named Campaign. that column could have one of three unique values, which are IVR, City, City2`. So the rows are like this:
I have a datatable has data like this format
........ IVR........
.........IVR........
**.........IVR........**
.........City1......
.........City1......
**.........City1......**
.........City2......
.........City2......
**.........City2......**
I want to take the last row of each unique value for that column, In other words, I want to take the rows that are bold. I did almost everything like this:
var cRows = new Dictionary<string, DataRow>(StringComparer.InvariantCultureIgnoreCase);
foreach (DataRow oRow in DTgraph.Rows)
{
var sKey = oRow["Campaign"].ToString();
if (!cRows.ContainsKey(sKey))
{
cRows.Add(sKey, oRow);
}
else
{
cRows[sKey] = oRow;
}
}
var oNewTable = DTgraph.Clone();
foreach (var oRow in cRows.Values)
{
oNewTable.Rows.Add(oRow);
}
As you see, I put the data in dictionary and transferred the dictionary to a datatable at the end.
My problem is that on this line:
cRows.Add(sKey, oRow);
I get an error:
The row is already belongs to another datatable
Note: I need to solve that exception, I don't need a new way of doing my goal
Note: I was wrong, the exception is on this line
oNewTable.Rows.Add(oRow);
To be honest I don't 100% understand your question, however to fix the exception:
The row is already belongs to another datatable.
Change:
oNewTable.Rows.Add(oRow);
To:
oNewTable.ImportRow(oRow);
Alternatively create a new row and clone the ItemArray.
foreach (var oRow in cRows.Values)
{
var newRow = oNewTable.NewRow();
newRow.ItemArray = oRow.ItemArray.Clone() as object[];
oNewTable.Rows.Add(newRow);
}
Use NewRow() function of the new table and then use oRow.ItemArray property to get values from the source row and copy them the newly created row's ItemArray. An example would be:
Array.Copy(oRow.ItemArray, oNewTable.NewRow().ItemArray, oRow.ItemArray.Length)
However, remember that this would not preserve original values and current state from the source row (which I don't think you're using here anyway). If those things matter, go for ImportRow() solution which preserves source row's state when copying.
I have list view the data will be displayed in list view from data table
like this i have done but i have problem at datarow 6
dt = classes.xxxxx.GetData(sql, mf);
if (dt != null)
{
ListViewItem newitem = null;
lstviewcashmembers.Items.Clear();
lstviewcashmembers.BeginUpdate();
foreach (DataRow dr in dt.Rows)
{
newitem = lstviewcashmembers.Items.Add(dr[0].ToString());
newitem.SubItems.Add(dr[1].ToString());
newitem.SubItems.Add(dr[2].ToString());
newitem.SubItems.Add(dr[3].ToString());
newitem.SubItems.Add(dr[4].ToString());
newitem.SubItems.Add(dr[5].ToString());
newitem.SubItems.Add(dr[6].ToString());
newitem.SubItems.Add(dr[7].ToString());
newitem.SubItems.Add(dr[8].ToString());
newitem.SubItems.Add(dr[9].ToString());
newitem.SubItems.Add(dr[10].ToString());
newitem = null;
}
lstviewcashmembers.EndUpdate();
}
my problem is like I got original value coming from database is 25.00000 at dr[6]
I mean in this line newitem.SubItems.Add(dr[6].ToString());
But I have to show only two decimal places like this 25.00
Would any one help this?
Use this:
dr[6].ToString("N2")
Update:
((double)dr[6]).ToString("N2")
The N2 must be done on a numeric type, so the cast is necessary on the DataRow object.
try this:
string r = "1000.123456";
var t = string.Format("{0:#.##}",decimal.Parse(r)); //1000.12
As Jason Down give the Correct Answer. Try dr[6].ToString("0.00") also
And try to read Standard Numeric Format Strings and Custom Numeric Format Strings For More Information About Format.
Happy Coding.
I have a DataView, which has been sorted in some order. How can I retrieve the values using an index.
Something like this:
if(dv.rows[0]["name"]=="xxx")
{
--- do something ---
}
else
--- something else ---
Did you try:
DataRowView rowView = dv[index];
Try the following code
Move the sorted DataView to DataTable like
DataTable dt = dv.ToTable();
Then use
if (dt.Rows[0]["name"] == "xxx")
{
[...]
}
It will work.
Rather than converting the whole thing back to a Table, you can work with the DataView directly:
To get a row from a DataView, you use the Item property, which returns a DataRowView, and you can then call Item to get at the cells, all of which can be shortened to:
// Returns object, so needs to be cast to your required type:
if ((string)dv[0]["CellName"] == "ABCD")
{
[...]
}
I don't quite know if this is the answer you're looking for:
if (dv.Rows[0].Cells["CellName"].Value == "ABCD")
{
}
The direct use of the DataRowView is simpler than converting the dv back to a DataTable (where it probably came from to begin with), I think.
var currRow = dv[0]; currRow["your_col_name"]?.ToString();