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();
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.
EDIT: Solved this myself - obviously won't work as sorting the dataTable doesn't sort the underlying data - created a dataView from the table, works fine.
I have a datatable which I am sorting and then iterating through to remove duplicate values in one column, however the output is not as expected.
Datatable structure:
infoRow["Title"]
infoRow["QuickLink"]
infoRow["Description"]
infoRow["Date"]
infoRow["MonthName"]
I'm sorting like this, which works fine, and produces a table ordered in ascending month order:
dataTable = dataTable.DefaultView.ToTable(true);
dataTable.DefaultView.Sort = "Date asc";
After the sort, I'm using the code below to compare each row to the previous, and if the MonthName value is the same, replaced it with an empty string:
string prevMonthName = "";
foreach (DataRow row in dtEvents.Rows)
{
string strMonthName = row["MonthName"].ToString();
if (strMonthName == prevMonthName)
{
row["MonthName"] = "";
row.AcceptChanges();
}
prevMonthName = strMonthName;
}
So, the problem I'm having is that even when I run the MonthName loop after the sort, it appears to be running against the unsorted data. It's like DefaultView.Sort only affects the rendered output without physically reordering the table, hence the second part of the code doesn't produce the result I need. Should I maybe be using DataView or am I just way off track...
I was actually having a similar, but slightly different problem and your question gave me an idea. As it turns out, your code was incredibly close to what you (and I) need. All you need to do is flip those two lines of sorting code like so:
dataTable.DefaultView.Sort = "Date ASC";
dataTable = dataTable.DefaultView.ToTable(true);
Now, the first line of code sorts the DefaultView. This would be enough for your DataGridView or ComboBox or whatever you're using for display, because they make use of the DefaultView. However, the DataTable, itself, remains unsorted. Therefore, the second line sets the DataTable to look exactly like the sorted DefaultView.
I just noticed your edit at the top which says you've solved it. That 'solution' seems to be more of a workaround. Seeing as how you had the right code but in the wrong order, I figured you would be interested in this answer.
Assuming that dtEvents is referencing the same object as datatable, you could try this:
string prevMonthName = "";
foreach (DataRowView row in dtEvents.DefaultView)
{
string strMonthName = row["MonthName"].ToString();
if (strMonthName == prevMonthName)
{
row["MonthName"] = "";
row.AcceptChanges();
}
prevMonthName = strMonthName;
}
Just for fun I figured out how to do this using Linq to SQL (assuming I had a sql table with your above schema). Since I spent the time figuring it out, I thought I might as well share it.
// Order the table and add an index column
var ordered = MonthTests.OrderBy(mt => mt.Date)
.AsEnumerable()
.Select((mt, index) => new
{
OrderId = index,
Record = mt
});
// Select out what we want
var query = from item in ordered
let prev = ordered.FirstOrDefault (q => q.OrderId == (item.OrderId-1))
select new
{
Title = item.Record.Title,
QuickLink = item.Record.QuickLink,
Date = item.Record.Date,
MonthName = (prev != null && prev.Record.MonthName == item.Record.MonthName) ? "" : item.Record.MonthName
};
Have fun.
DataRow[] headerRows = null;
headerRows = mappingTable.Select("FieldID LIKE '0_%'"); //mappingTable is of type DataTable.
I have three columns in the mappingTable "Id","Display", "Value"
Now, I need to get the Value where "Id" = 0_0_0 from the headerRows.
Is there any simple way to do this?
Thanks for any help.
If you have to use DataRow[] then with linq you can do this:
String value = (String)rows.Single(
row => String.Equals(row["Id"], "0_0_0"))["Value"];
You need to set the PrimaryKey on the DataTable and then you can use Find() on the Rows collection to find the row with that key.
dataTable.PrimaryKey = new DataColumn[] { dataTable.Columns["Id"] };
object value = dataTable.Rows.Find("0_0_0")["Value"];
You could use LINQ: but this might be overkill:
dt.AsEnumerable().Where(dr => dr.Field<object>("FieldId").StartsWith("0_"));
If you have to have DataRow[] then
headerRows = dt.AsEnumerable().Where(dr => dr.Field<object>("FieldId").StartsWith("0_")).ToArray();
From there you have only data rows that match your criteria, so you can cycle through for the value.
Now I use Select and use a criteria which select only new rows. But is there any kind of GetInsertedRows-method. If I remember correctly there is status for each row so naturally one can loop through them all but that's not elegant.
-Cheers -Matti
I like TypeT's answer but it may help to know that you always bind through a DataView to a DataTable and you can set it to filter on the rows state:
myDataSet.myTable.DefaultView.RowStateFilter = DataViewRowState.Added;
You can also create an additional DataView to look at the new or deleted rows, and then those Views won't byte each other:
var addedView = new DataView(myDataSet.myTable);
addedView.RowStateFilter = DataViewRowState.Added;
I came across this issue myself a while ago, however there's no nice way of pulling out the added rows. I've just trawled my repositories for you and found the DataTable implementation I used to use:
public class AdvancedDataTable : DataTable
{
public IEnumerable<DataRow> InsertedRowList
{
get
{
foreach (DataRow row in this.Rows)
{
if (row.RowState == System.Data.DataRowState.Added)
{
yield return row;
}
}
}
}
}
It's still doing an iteration, but it's nicely wrapped as an IEnumerable and you won't have to write the code more than once.
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