I am using the below query to find the the distinct value count from a dataset column. How to find similarly to a grid column.
var distinctRows = (from DataRow dRow in _ds.Tables[0].Rows
select dRow["colName"]).Distinct();
Ok..I'm still not sure why you want to do it without requerying the DataSource, but here's one way that might point you in the right direction. gv1 is the ID of your GridView, and for demonstration purposes I'll use the first column:
string[] rowValues = new string[gv1.Rows.Count];
for (int i = 0; i < gv1.Rows.Count; i++)
{
rowValues[i] = gv1.Rows[i].Cells[0].Text;
}
var distinctRows = (from r in rowValues
select r).Distinct();
This of course assumes that it's one cell per column, which may be a false (or at least bad) assumption.
UPDATE
Just saw this Can't seem to use Linq with ASP.Net Navigation menu answered by Jon Skeet, and think it might apply to the issue here.
var distinctRows = (from GridViewRow r in gv1.Rows
select r.Cells[0].Text).Distinct();
Courtesy of Jon's answer, to use LINQ in this case you need to Cast to IEnumerable (as I'm willing to bet the GridViewRowsCollection doesn't implement IEnumerable) by explicitly specifying the item, as above.
Your grid is probably bound to a data source in which case it makes more sense to use the linq query against the data source rather than the grid itself
Related
I have specific case of grouping items in ObjectListView. Usually one would choose column that is shown in the list and do GroupKeyGetter/GroupKeyToTitleConverter magic on that column. However, in my case the data I would like to group on is not supposed to be shown in ObjectListView. It exists only in Model. So far the only dirty workaround I've found is to make this data shown in ObjectListView, but set width of column 0.
Is there better way to group by data, which is not supposed to be shown in the view?
You can hide your column:
OLVColumn column = new OLVColumn("HiddenGroupColumn", "ModelProperty");
column.IsVisible = false;
column.GroupKeyGetter = delegate(object x)
{
return ((Model)x).ModelProperty;
};
First I will tell you some background, I needed to create a grid with dynamic columns, the column count would be based on user selection, in my DataTable, I added numbers to columns names to keep their name distinct, then I bind it with my girdview.
Now I need to rename columns headerText and remove the counter numbers from column headers, my gird has one more unbound column which is of type Image, when I try to loop my grid.columns using:
foreach (DataGridViewTextBoxColumn dgc in grdDistProcessing.Columns)
it gives me error
InvalidCastException:
Unable to cast object of type 'System.Windows.Forms.DataGridViewImageColumn' to type 'System.Windows.Forms.DataGridViewTextBoxColumn'.
I also used DataColumn but it gave me same error, another thread says we should use DataControlField but VS did not recognizing it, is it an ASP thing ? or I am missing a reference ?
Please Help.
Rgds,
if you have the var keyword available to you (c#3 and above i think).
foreach (var dgc in grdDistProcessing.Columns)
{
if(dgc is DataGridViewImageColumn)
{
//do stuff with it.
var tempDgc = (DataGridViewImageColumn)dgc; //cast it as needed.
//use it
}
}
Thanks scartag, your solution is working like a charm, by the way I explored another solution for the issue, I can just use a plain for loop.
`for (int i = 0; i < grdDistProcessing.Columns.Count; i++)
{
MessageBox.Show(grdDistProcessing.Columns[i].HeaderText);
}`
I'm trying to populate a combo box with data resulting from a LINQ query on a DataSet. The problem is, nothing is showing up in the combobox. At all.
var digits =
(from digit in DDDataSet.Digits.AsEnumerable()
where (!digit.pressed)
select new {DigitList = digit.name});
cboDigits.DataSource = digits.ToList();
cboDigits.DisplayMember = "DigitList";
Any ideas?
I think you need to:
cboDigits.DataBind();
after you set the DataSource and DisplayMember.
Hope this helps
just try this
var stuff = dg.Stuffs.Where(c=> c.admin !=1).ToList();
for (int i = 0; i < stuff.Count; i++)
{
string test = stuff.ElementAt(i).Name;
comboBox1.Items.Add(test);
}
Most controls do data binding automatically, which means that you typically do not need to call the method DataBind explicitly.
Linq when using ToList() won't be deferred, so all the data is computed. But, for combobox, it seems that you still need to use DataBind().
If you are using Winform, you do not need DataBind to be called. If you are using Asp.Net you will need to.
I have a datatable bound to a datagridview. However, the ordering of columns is messed up. I already made a column headers for each field put dataproperty name. I arranged it in the designer view. However, if i run the program column headers doesn't follow my arrangement. =_=. Does anybody know how to solve this....
EDIT::
I've Tried this approach. Is it Okay?
void SortDataGridViewColumns(DataGridView dgv)
{
var list = from DataGridViewColumn c in dgv.Columns
orderby c.Index
select c;
int i = 0;
foreach (DataGridViewColumn c in list)
{
c.DisplayIndex = i++;
}
}
***I've got this here but I use Index instead of Headertext. CASE CLOSED! LOL
I think you wil need to change the column order in runtime.
From MSDN:
When you use a DataGridView to display data from a data source, the columns in the data source's schema sometimes do not appear in the order you would like to display them. You can change the displayed order of the columns by using the DisplayIndex property of the DataGridViewColumn class.
You can change the order of the columns like this:
private void AdjustColumnOrder()
{
customersDataGridView.Columns["CustomerID"].Visible = false;
customersDataGridView.Columns["ContactName"].DisplayIndex = 0;
customersDataGridView.Columns["ContactTitle"].DisplayIndex = 1;
customersDataGridView.Columns["City"].DisplayIndex = 2;
customersDataGridView.Columns["Country"].DisplayIndex = 3;
customersDataGridView.Columns["CompanyName"].DisplayIndex = 4;
}
http://msdn.microsoft.com/en-us/library/wkfe535h.aspx#Y0
If you're going t use it frequently, I recomend you to make use of extension methods to add sintactic sugar and make it easy to read and maintain.
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.