in the next example how can I know the current row index?
foreach (DataRow temprow in temptable.Rows)
{
//this.text = temprow.INDEX????
}
You have to create one yourself
var i = 0;
foreach (DataRow temprow in temptable.Rows)
{
this.text = i;
// etc
i++;
}
or you can just do a for loop instead.
I have a type in MiscUtil which can help with this - SmartEnumerable. It's a dumb name, but it works :) See the usage page for details, and if you're using C# 3 you can make it even simpler:
foreach (var item in temptable.Rows.AsSmartEnumerable())
{
int index = item.Index;
DataRow value = item.Value;
bool isFirst = item.IsFirst;
bool isLast = item.IsLast;
}
If you can use Linq, you can do it this way:
foreach (var pair in temptable.Rows.Cast<DataRow>()
.Select((r, i) => new {Row = r, Index = i}))
{
int index = pair.Index;
DataRow row = pair.Row;
}
You actually Don't. One of the beauties with foreach is that you don't have the extra set of code handling incrementing and checks on the length.
If you want to have your own Index you would have to do something like this
int rowindex = 0;
foreach (DataRow temprow in temptable.Rows)
{
//this.text = temprow.INDEX????
this.text = rowindex++;
}
int rowIndex = temptable.Rows.IndexOf(temprow);
It's not possible with a standard foreach loop. The simplest way is to use a for loop
for ( int i = 0; i < temptable.Rows.Count; i++ ) {
DataRow temprow = (DataRow)temptable.Rows[i];
...
}
Another option is to use an extension method
public static void ForEachIndex<T>(this IEnumerable<T> e, Action<T,int> del) {
var i = 0;
foreach ( var cur in e ) {
del(cur,i);
}
}
...
temptable.Rows.Cast<DataRow>.ForEachIndex((cur,index)
{
...
});
Hey there's a much faster way I think. No iteration required!
First, declare a static variable for the Friend RowID Field of the DataRow:
Private Shared RowIDFieldInfo As System.Reflection.FieldInfo = GetType(DataRow).GetField("_rowID", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance)
Then All you need to do to use it is:
RowIDFieldInfo.GetValue(MyDataRow) - 1
I have not tested this after resorting or filtering.
In my case I haven't a need to do that, so this works.
Better late than never...
foreach (DataRow temprow in temptable.Rows)
{
temptable.Rows.IndexOf(temprow);
}
Write any Cell number and get RowIndex
foreach (var item in datagridview.Rows)
{
//TextBox1.Text= item.Cells[0].RowIndex.ToString();
}
Either use a for-loop, or use an integer follow along:
int count =0;
foreach (DataRow temprow in temptable.Rows)
{
//count is the index of the row in the array temptable.Rows
//this.text = temprow.INDEX????
++count;
}
You can use the standard for loop to get the index
for(int i=0; i<temptable.Rows.Count; i++)
{
var index = i;
var row = temptable.Rows[i];
}
While LFSR's answer is right, I'm pretty sure calling .IndexOf on just about any collection/list is going to enumerate the list until it finds a the matching row. For large DataTable's this could be slow.
It might be better to for (i = 0; i < temptable.Rows.Count; i++) { ... } over the table. That way you have the index without imposing a find-the-index tax.
The alternative way to retrieve data by using index instead of using column name
foreach (DataRow temprow in temptable.Rows)
{
String col1 = temprow[0].ToString().Trim();
String col2 = temprow[1].ToString().Trim();
}
Hope it help
Related
I have a datatable with 10 columns. I have to check if the cell values in each of the columns contains value A or D, if so I have to replace 'A' with '150' and 'D' with '250' respectively.
I am trying with this ::
foreach (DataRow dr in dt.Rows)
{
foreach(var item in dr.ItemArray)
{
if( item.ToString()=="A")
{
item.ToString().Replace("A", "150");
}
if (item.ToString() == "D")
{
item.ToString().Replace("A", "250");
}
}
}
but the values are not replaced. Why is it so? What is the error with this code ?
Replacing a string is not the whole point in the question. There are some important points, which are ignored by the other answers.
Assigning a value to an element of the item array will not change column value.
Assigning value to a variable containing the column value will not change the column value.
To replace column values using ItemArray, you need to assign a new array the ItemArray property.
When trying to replace the ItemArray property, if there is a read-only column, then setting item array will throw an exception.
And the point which is already mentioned by other answers, Replace method of the string will return the result replaced string, it will not change the source string.
Just for your information to have a better understanding about ItemArray property, it's the way that the property works, (in short):
Public object[] ItemArray {
get {
var values = new object[Columns.Count];
for (int i = 0; i < values.Length; i++) {
values[i] = Columns[i];
}
return values;
}
set {
for (int i = 0; i < values.Length; i++) {
//Checks if the column is writable and value is valid
Columns[i] = value[i];
}
}
}
You can read the whole source code as well.
So as a conclusion, the following pieces of code are wrong and will do nothing for you:
Wrong: row.ItemArray[i] = "something"; → Will not change column[i]
Wrong: var item = row[i]; item = "something"; → Will not change column[i]
Wrong var s = "something"; s.Replace("s", "x"); → Will not change s.
Example - Using ItemArray
Please be aware, if there is a read-only column in the data table, the following code will raise an exception:
foreach (DataRow r in dt.Rows)
{
var a = r.ItemArray;
for (int i = 0; i < dt.Columns.Count; i++)
{
if ($"{a[i]}" == "A") // if($"{a[i]}".Contains("A"))
a[i] = "150"; // a[i] = $"{a[i]}".Replace("A", "150");
if ($"{a[i]}" == "D")
a[i] = "250";
}
r.ItemArray = a;
};
Example - Using Columns Indexer
foreach (DataRow r in dt.Rows)
{
foreach (DataColumn c in dt.Columns)
{
if (c.ReadOnly)
continue;
if ($"{r[c]}" == "A") // if($"{r[c]}".Contains("A"))
r[c] = "150"; // r[c] = $"{r[c]}".Replace("A", "150");
else if ($"{r[c]}" == "D")
r[c] = "250";
}
}
I have this code:
foreach (var row in App.cardSetWithWordCounts)
{
details.Children.Add(new SeparatorTemplate());
// do some tasks for every row
// in this part of the loop ...
}
I would like to not do the adding of a SeparatorTemplate BUT I would like to do the other tasks on the first run of the foreach. Does anyone have a suggestion on how I can do this?
I want to execute the rest of the code in the foreach but not the line adding the template on the first time around.
If you want to skip the first row, you can use Skip:
foreach (var row in App.cardSetWithWordCounts.Skip(1))
If you want to know the exact row number, use the Select overload:
foreach (var x in App.cardSetWithWordCounts.Select((r, i) => new { Row = r, Index = i })
{
// use x.Row and x.Index
}
The simpliest would be:
bool isFirstRun = true;
foreach (var row in App.cardSetWithWordCounts)
{
if(isFirstRun)
isFirstRun = false;
else
details.Children.Add(new SeparatorTemplate());
// do some tasks for every row
// in this part of the loop ...
}
You can use Skip method for this purpose:
foreach (var row in App.cardSetWithWordCounts.Skip(1))
Update:
foreach (var row in App.cardSetWithWordCounts.Select((c, index) => new { Row = c, Index = index })
{
if(row.Index != 0)
}
Just don't forget to add the following line to your using directives:
using System.Linq;
You can try to create an Extention method.
Action second parameter is the iterator index.
public static class ExtenstionArray
{
public static void ForEach<T>(this IEnumerable<T> sequence, Action< T, int> action)
{
int i = 0;
foreach (T item in sequence)
{
action(item,i);
i++;
}
}
}
Then use like this.
App.cardSetWithWordCounts.ForEach((i, idx)=>{
if(idx == 0){
details.Children.Add(new SeparatorTemplate());
}
// other logic
});
c# online
var firstRow = true;
foreach(var row in App.cardSetWithWordCounts)
{
if(firstRow)
{
firstRow = false;
}
else
{
// rest of the code here
}
}
I am using foreach loop and inside that loop I declared datarow
DataSet ds = Business.Site.GetSiteActiveModulesWithStatus(siteId);
foreach (DataRow dr in ds.Tables[0].Rows)
How can I implement this datarow outside foreach loop and how can I use for loop instead of foreach loop?
To loop in a for:
for(int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
//To acess the row
DataRow row = ds.Tables[0].Rows[i];
}
Outside the for, to acess a specific DataRow you can do like this:
//Change 0 to other numbers to acess other rows
DataRow row = ds.Tables[0].Rows[0];
To access the row variable outside of the loop, you simple have to declare it outside:
DataRow rowFound = null;
for(int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
var currentRow = ds.Tables[0].Rows[i];
if(true /*To do: define some matching criteria*/)
{
rowFound = currentRow;
}
}
if(rowFound != null)
{
// We found some matching, what shall we do?
}
But you could write the same also in a LINQish style:
var rowFound = ds.Tables[0].AsEnumerable()
.Where(row => true /*To do: define some matching criteria*/)
.FirstOrDefault();
All code in this answer is untested.
I have a CheckedListBox and I would like to check all the items that are in another List.
This code does not work since the CheckedItems property is read-only and the types do not match, but it gives the best idea of what I want to do.
checkedListBox1.DataSource = DataSetSelectAll().Tables[0];
checkedListBox1.ValueMember = "id_table";
checkedListBox1.DisplayMember = "name";
List<tableClass> list = MyCheckedList();
checkedListBox1.CheckedItems = list;
I know this is wrong but do not know how to explain it better.
Its not possible to set(check) many items at a time like this, checkedListBox1.CheckedItems = list;
better you can use for loop like:
List<tableClass> list = MyCheckedList();
for (int count = 0; count < checkedListBox1.Items.Count; count++)
{
if (list.Contains(checkedListBox1.Items[count].ToString()))
{
checkedListBox1.SetItemChecked(count, true);
}
}
andy's answer is right but I have an easier solution. My solution works in windows application.
DataTable dt = MyCheckedList();
foreach (DataRow dr in dt.Rows)
{
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
if (dr["valueMember"].ToString() == ((DataRowView)checkedListBox1.Items[i])[0].ToString())
{
checkedListBox1.SetItemChecked(i, true);
}
}
}
Note: dt must fill with a dataTable which has all checkedList Values.
I'm not sure why, but I SetItemChecked(index, tf) wasn't giving me what I wanted. This is how I solved it - explicitly setting the CheckedState.
for (int i = 0; i < myCheckedListBox.Items.Count; i++)
{
if (boolList[i])
{
myCheckedListBox.SetItemCheckState(i, CheckState.Checked);
} else
{
myCheckedListBox.SetItemCheckState(i, CheckState.Unchecked);
}
}
I am trying to store the values of each of my rows in a string.
If I try to do DataGridView.Rows.ToString() I get
System.Windows.Forms.DataGridViewRowCollection
Not even close to what I need.
Any ideas?
I think you're looking for something on a per row basis. If so, I suggest the following.
private static IEnumerable<string> GetRowValues(this DataGridView dgv)
{
var list = new List<string>(dgv.Rows.Count);
foreach (DataGridViewRow row in dgv.Rows)
{
var sb = new StringBuilder();
foreach (DataGridViewCell cell in row.Cells)
{
sb.Append(cell.ToString());
}
list.Add(sb.ToString());
}
return list.AsReadOnly();
}
You need to do something like this:
StringBuilder sb = new StringBuilder();
for(int row=0; row<DataGridView.Rows.Count; row++)
{
for(int col=0; col < DataGridView.Columns.Count; col++)
{
sb.Append(DataGridView.Row[row][col].ToString());
}
}
sb.ToString(); // that will give you the string you desire
EDIT I didn't run this through to check that it runs but it should at least give you a starting point. Also, this will give you all rows. If you want just one row, change the variable row to the row number you need (keep in mind that it is zero-based).
Use the for each statement to iterate through each row in the Datagridview.
foreach (DataGridViewRow datarow in dataGridView.Rows)
{
string col1 = datarow.Cells["Col1"].Value.ToString();
string col2 = datarow.Cells["Col2"].Value.ToString();
string col3 = datarow.Cells["Col3"].Value.ToString();
}
Foreach(Var row in DataGridView.Rows)
{
Foreach(Var cell in row.Cells)
{
Var str = cell; // this is the string you want
}
}
Something like the code above. Excuse the formatting typed on iPad.