I have a method as such :
public void setResults(Documents[] doc)
{
//I call a method to set the columns
setColumns(doc[0].getColumnsToDisplay())
//Here i populate the DataGrid
foreach (Documents element in doc)
{
/dt is a datatable
DataRow dr = dt.NewRow();
foreach (string col in results[0].getColumnsToDisplay())
{
object val;
(element.getAttributes() as IDictionary<string, object>).TryGetValue(col, out val);
dr[col] = val.ToString();
}
dt.Rows.Add(dr);
}
gridSearchResults.DataSource = dt;
}
Is there a way to store "doc" reference on each row ? so that if i select a row, i can be able to return the "doc" object ? Looking for some kind of Tag property alternative for rows or something different.
When you want to show a list of your objects in a DataGridView, you don't need to use a DataTable. You can simply set your list as DataSource of your DataGridView:
public void setResults(Documents[] doc)
{
gridSearchResults.DataSource = doc;
}
Then if you want to know the object behind the row, you can simply use DataBoundItem property of the DataGridViewRow and cast it to your object type:
var documents= (Documents)gridSearchResults.Rows[0].DataBoundItem;
For more information and samples, you can see:
How to: Access Objects Bound to Windows Forms DataGridView Rows.
If you want to show only some columns in the DataGridView, add the columns you need this way:
this.dataGridView1.Columns.Clear();
this.dataGridView1.AutoGenerateColumns = false;
//Create Column
var column1 = new DataGridViewTextBoxColumn()
{
Name = "firstNameColumn", /*Name of Column*/
HeaderText = "First Name", /*Title of Column*/
DataPropertyName = "FirstName" /*Name of the property to bind to cilumn*/
};
//Add column to grid
this.dataGridView1.Columns.Add(column1);
You should use DataGridView instead of DataGrid. I assume you're trying to get the object after postback.
//DO NECESSARY NULL CHECKS!!!
DataRow row = (gridSearchResults.SelectedRows[0].DataBoundItem as DataRowView).Row;
Documents selected = (Documents)row;
I've been struggling with this for days, and I'm getting DataTables and dataGridViews all mixed up.
I have a WinForms program, which has a DataGridView, dataGridView1, and a DataTable, errors.
public static DataTable errors = new DataTable();
dataGridView1.DataSource = errors;
Now, further down, in a method called ValidateText, I read data from a text file, line by line, into an array, where I also define the columns for the errors datatable:
errors.Columns.Add("Account Number");
errors.Columns.Add("Customer Name");
errors.Columns.Add("Country");
errors.Columns.Add("State");
errors.Columns.Add("Ship-to Country");
errors.Columns.Add("Ship-to State");
var lines = File.ReadAllLines(file);
foreach (string line in lines)
{.
.
.
string []items=line.Split('\t').ToArray();
errors.Rows.Add(items[0], items[1],...items[5]);
And that works just fine when I run it. the thing is, I want to make the "Country" column have a combo box in it, so when the program is run, and the data is displayed in the dataGridView1, the user will have the opportunity to select a new country, if they want, from the "Countries" column. And further down in the program, I've indeed defined a
method that creates a DataGridViewComboBoxColumn
private DataGridViewComboBoxColumn CreateComboBoxColumn()
{
DataGridViewComboBoxColumn buildCountries = new DataGridViewComboBoxColumn();
buildCountries.HeaderText = "List of Countries";
DataTable dataTable = new DataTable();
dataTable.Columns.Add("Keys");
dataTable.Columns.Add("Values");
KeyValuePair<string, string>[] array = CountryList.ToArray();
foreach (KeyValuePair<string, string> kvp in array)
{
dataTable.Rows.Add(kvp.Key, kvp.Value);
}
buildCountries.DataSource = dataTable;
buildCountries.DisplayMember = "Values";
buildCountries.ValueMember = "Keys";
return buildCountries;
}
The thing that I am having problems with, is how do I get that combo box that I've created in that last method, into the "Countries" column I've created above? I feel like I'm not getting something with DataGridView and DataTable. You bind a DataTable to a DataGridView, but adding this DataGridViewComboBoxColumn seems to be hard.
Thanks,
Amanda
this is just my suggestion, the .NET Framework had a already list of countries. so you can use this class. i forgot who created this code :)
public static class CountryEntries
{
public static IEnumerable<Country> GetCountries()
{
return from ri in
from ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures)
select new RegionInfo(ci.LCID)
orderby ri.DisplayName
group ri by ri.TwoLetterISORegionName into g
select new Country
{
CountryId = g.Key,
Title = g.First().DisplayName
};
}
public class Country
{
public string CountryId { get; set; }
public string Title { get; set; }
}
}
I'm having a Structure like
X={ID="1", Name="XX",
ID="2", Name="YY" };
How to dump this data to a DataGridView of two columns
The gridView is like
ID | Name
Can we use LINQ to do this. I'm new to DataGridView Pleaese help me to do this..
Thanks in advance
first you need to add 2 columns to datagrid. you may do it at design time. see Columns property.
then add rows as much as you need.
this.dataGridView1.Rows.Add("1", "XX");
Let's assume you have a class like this:
public class Staff
{
public int ID { get; set; }
public string Name { get; set; }
}
And assume you have dragged and dropped a DataGridView to your form, and name it dataGridView1.
You need a BindingSource to hold your data to bind your DataGridView. This is how you can do it:
private void frmDGV_Load(object sender, EventArgs e)
{
//dummy data
List<Staff> lstStaff = new List<Staff>();
lstStaff.Add(new Staff()
{
ID = 1,
Name = "XX"
});
lstStaff.Add(new Staff()
{
ID = 2,
Name = "YY"
});
//use binding source to hold dummy data
BindingSource binding = new BindingSource();
binding.DataSource = lstStaff;
//bind datagridview to binding source
dataGridView1.DataSource = binding;
}
My favorite way to do this is with an extension function called 'Map':
public static void Map<T>(this IEnumerable<T> source, Action<T> func)
{
foreach (T i in source)
func(i);
}
Then you can add all the rows like so:
X.Map(item => this.dataGridView1.Rows.Add(item.ID, item.Name));
LINQ is a "query" language (thats the Q), so modifying data is outside its scope.
That said, your DataGridView is presumably bound to an ItemsSource, perhaps of type ObservableCollection<T> or similar. In that case, just do something like X.ToList().ForEach(yourGridSource.Add) (this might have to be adapted based on the type of source in your grid).
you shoud do like this form your code
DataGridView.DataSource = yourlist;
DataGridView.DataBind();
I have a "populate combobox", and I'm so happy with it that I've even started using more comboboxes. It takes the combobox object by reference with the ID of the "value set" (or whatever you want to call it) from a table and adds the items and their respective values (which differ) and does the job.
I've recently had the brilliant idea of using comboboxes in a gridview, and I was happy to notice that it worked JUST LIKE a single combobox, but populating all the comboboxes in the given column at the same time.
ObjComboBox.Items.Add("yadayada");
//works just like
ObjComboBoxColumn.Items.Add("blablabla");
But When I started planning how to populate these comboboxes I've noticed: There's no "Values" property in ComboBoxDataColumn.
ObjComboBox.Values = whateverArray;
//works, but the following doesn't
ObjComboBoxColumn.Values = whateverArray;
Questions:
0 - How do I populate it's values ? (I suspect it's just as simple, but uses another name)
1 - If it works just like a combobox, what's the explanation for not having this attribute ?
-----[EDIT]------
So I've checked out Charles' quote, and I've figured I had to change my way of populating these bad boys. Instead of looping through the strings and inserting them one by one in the combobox, I should grab the fields I want to populate in a table, and set one column of the table as the "value", and other one as the "display". So I've done this:
ObjComboBoxColumn.DataSource = DTConfig; //Double checked, guaranteed to be populated
ObjComboBoxColumn.ValueMember = "Code";
ObjComboBoxColumn.DisplayMember = "Description";
But nothing happens, if I use the same object as so:
ObjComboBoxColumn.Items.Add("StackOverflow");
It is added.
There is no DataBind() function.
It finds the two columns, and that's guaranteed ("Code" and "Description") and if I change their names to nonexistant ones it gives me an exception, so that's a good sign.
-----[EDIT]------
I have a table in SQL Server that is something like
code | text
—————
1 | foo
2 | bar
It's simple, and with other comboboxes (outside of gridviews) i've successfully populated looping through the rows and adding the texts:
ObjComboBox.Items.Add(MyDataTable.Rows[I]["MyColumnName"].ToString());
And getting every value, adding it into an array, and setting it like:
ObjComboBox.Values = MyArray;
I'd like to populate my comboboxColumns just as simply as I do with comboboxes.
I don't mean to sound obnoxious, but do you know there's documentation for all this stuff?
From http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcomboboxcolumn.aspx:
You can populate the column drop-down
list manually by adding values to the
Items collection. Alternatively, you
can bind the drop-down list to its own
data source by setting the column
DataSource property. If the values are
objects in a collection or records in
a database table, you must also set
the DisplayMember and ValueMember
properties. The DisplayMember property
indicates which object property or
database column provides the values
that are displayed in the drop-down
list. The ValueMember property
indicates which object property or
database column is used to set the
cell Value property.
EDIT:
From your edit, it sounds like you might be trying to use non-public properties of the underlying type for DisplayMember and/or ValueMember. Or if your combobox datasource is a DataTable, make sure it has "Code" and "Description" columns.
Here's a simple demo. I create a list of Foo's and assign it as the DataSource of my combobox column. Just create a winforms application and paste this in.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// this will be the datasource for the combo box column; you could also bind it to a dataset
List<Foo> foos = new List<Foo>() {
new Foo() { FooID = 0, FooName = "No Foo." },
new Foo() { FooID = 1, FooName = "Foo Me Once" },
new Foo() { FooID = 2, FooName = "Foo Me Twice" },
new Foo() { FooID = 3, FooName = "Pity The Foo!" }
};
DataGridView dataGridView1 = new DataGridView();
dataGridView1.AutoGenerateColumns = false;
// add normal text column
DataGridViewColumn column = new DataGridViewTextBoxColumn();
column.DataPropertyName = "MyText";
column.Name = "Text";
dataGridView1.Columns.Add(column);
// add the combo box column
DataGridViewComboBoxColumn comboCol = new DataGridViewComboBoxColumn();
comboCol.Name = "Foo";
// bind it to the list of foos to populate it
comboCol.DataSource = foos;
// specify which property of the grid's datasource to bind
comboCol.DataPropertyName = "MyFoo";
// specify the property of the combo's datasource to bind
comboCol.ValueMember = "FooID";
// specify the property of the combo's datasource to display
comboCol.DisplayMember = "FooName";
dataGridView1.Columns.Add(comboCol);
// add some data
BindingSource bindingSource1 = new BindingSource();
bindingSource1.Add(new BusinessObject(1, "You say"));
bindingSource1.Add(new BusinessObject(2, "George says"));
bindingSource1.Add(new BusinessObject(3, "Mr. T says"));
bindingSource1.Add(new BusinessObject());
dataGridView1.DataSource = bindingSource1;
Controls.Add(dataGridView1);
dataGridView1.Dock = DockStyle.Fill;
}
class Foo
{
public int FooID { get; set; }
public string FooName { get; set; }
}
class BusinessObject
{
public BusinessObject(int foo, string text)
{
MyFoo = foo;
MyText = text;
}
public BusinessObject()
{
MyFoo = 0;
MyText = "";
}
public string MyText { get; set; }
public int MyFoo { get; set; }
}
}
I'm curious as to the best route (more looking towards simplicity, not speed or efficiency) to sort a DropDownList in C#/ASP.NET - I've looked at a few recommendations but they aren't clicking well with me.
Edit: Folks, I do not have control over how the data comes into the DropDownList - I cannot modify the SQL.
If you get a DataTable with the data, you can create a DataView off of this and then bind the drop down list to that. Your code would look something like...
DataView dvOptions = new DataView(DataTableWithOptions);
dvOptions.Sort = "Description";
ddlOptions.DataSource = dvOptions;
ddlOptions.DataTextField = "Description";
ddlOptions.DataValueField = "Id";
ddlOptions.DataBind();
Your text field and value field options are mapped to the appropriate columnns in the data table you are receiving.
A C# solution for .NET 3.5 (needs System.Linq and System.Web.UI):
public static void ReorderAlphabetized(this DropDownList ddl)
{
List<ListItem> listCopy = new List<ListItem>();
foreach (ListItem item in ddl.Items)
listCopy.Add(item);
ddl.Items.Clear();
foreach (ListItem item in listCopy.OrderBy(item => item.Text))
ddl.Items.Add(item);
}
Call it after you've bound your dropdownlist, e.g. OnPreRender:
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
ddlMyDropDown.ReorderAlphabetized();
}
Stick it in your utility library for easy re-use.
Assuming you are running the latest version of the .Net Framework this will work:
List<string> items = GetItemsFromSomewhere();
items.Sort((x, y) => string.Compare(x, y));
DropDownListId.DataSource = items;
DropDownListId.DataBind();
DropDownList takes any IEnumerable as a DataSource.
Just sort it using LINQ.
I usually load a DropDownList with values from a database table, so the easiest way is to sort your results as desired with the ORDER BY clause of your SELECT statement, and then just iterate through the results and dump them into the DropDownList.
Take a look at the this article from CodeProject, which rearranges the content of a dropdownlist. If you are databinding, you will need to run the sorter after the data is bound to the list.
It is recommended to sort the data before databinding it to the DropDownList but in case you can not, this is how you would sort the items in the DropDownList.
First you need a comparison class
Public Class ListItemComparer
Implements IComparer(Of ListItem)
Public Function Compare(ByVal x As ListItem, ByVal y As ListItem) As Integer _
Implements IComparer(Of ListItem).Compare
Dim c As New CaseInsensitiveComparer
Return c.Compare(x.Text, y.Text)
End Function
End Class
Then you need a method that will use this Comparer to sort the DropDownList
Public Shared Sub SortDropDown(ByVal cbo As DropDownList)
Dim lstListItems As New List(Of ListItem)
For Each li As ListItem In cbo.Items
lstListItems.Add(li)
Next
lstListItems.Sort(New ListItemComparer)
cbo.Items.Clear()
cbo.Items.AddRange(lstListItems.ToArray)
End Sub
Finally, call this function with your DropDownList (after it's been databound)
SortDropDown(cboMyDropDown)
P.S. Sorry but my choice of language is VB. You can use http://converter.telerik.com/ to convert the code from VB to C#
Another option is to put the ListItems into an array and sort.
int i = 0;
string[] array = new string[items.Count];
foreach (ListItem li in dropdownlist.items)
{
array[i] = li.ToString();
i++;
}
Array.Sort(array);
dropdownlist.DataSource = array;
dropdownlist.DataBind();
I agree with sorting using ORDER BY when populating with a database query, if all you want is to sort the displayed results alphabetically. Let the database engine do the work of sorting.
However, sometimes you want some other sort order besides alphabetical. For example, you might want a logical sequence like: New, Open, In Progress, Completed, Approved, Closed. In that case, you could add a column to the database table to explicitly set the sort order. Name it something like SortOrder or DisplaySortOrder. Then, in your SQL, you'd ORDER BY the sort order field (without retrieving that field).
What kind of object are you using for databinding? Typically I use Collection<T>, List<T>, or Queue<T> (depending on circumstances). These are relatively easy to sort using a custom delegate. See MSDN documentation on the Comparison(T) delegate.
var list = ddl.Items.Cast<ListItem>().OrderBy(x => x.Text).ToList();
ddl.DataSource = list;
ddl.DataTextField = "Text";
ddl.DataValueField = "Value";
ddl.DataBind();
Try it
-------Store Procedure-----(SQL)
USE [Your Database]
GO
CRATE PROC [dbo].[GetAllDataByID]
#ID int
AS
BEGIN
SELECT * FROM Your_Table
WHERE ID=#ID
ORDER BY Your_ColumnName
END
----------Default.aspx---------
<asp:DropDownList ID="ddlYourTable" runat="server"></asp:DropDownList>
---------Default.aspx.cs-------
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<YourTable> table= new List<YourTable>();
YourtableRepository tableRepo = new YourtableRepository();
int conuntryInfoID=1;
table= tableRepo.GetAllDataByID(ID);
ddlYourTable.DataSource = stateInfo;
ddlYourTable.DataTextField = "Your_ColumnName";
ddlYourTable.DataValueField = "ID";
ddlYourTable.DataBind();
}
}
-------LINQ Helper Class----
public class TableRepository
{
string connstr;
public TableRepository()
{
connstr = Settings.Default.YourTableConnectionString.ToString();
}
public List<YourTable> GetAllDataByID(int ID)
{
List<YourTable> table= new List<YourTable>();
using (YourTableDBDataContext dc = new YourTableDBDataContext ())
{
table= dc.GetAllDataByID(ID).ToList();
}
return table;
}
}
I agree with the folks in sorting your data in the model before populating them to the DropDownList, so if you are populating this from a DB, it is a good thing to get them sorted already there using a simple order by clause, it will save you some cycles in the web server, and I am sure the DB will do it so much faster.
If you are populating this from another data source for example, XML file, using LINQ will be a good idea, or even any variation of Array.Sort will be good.
If your data is coming to you as a System.Data.DataTable, call the DataTable's .Select() method, passing in "" for the filterExpression and "COLUMN1 ASC" (or whatever column you want to sort by) for the sort. This will return an array of DataRow objects, sorted as specified, that you can then iterate through and dump into the DropDownList.
List<ListItem> li = new List<ListItem>();
foreach (ListItem list in DropDownList1.Items)
{
li.Add(list);
}
li.Sort((x, y) => string.Compare(x.Text, y.Text));
DropDownList1.Items.Clear();
DropDownList1.DataSource = li;
DropDownList1.DataTextField = "Text";
DropDownList1.DataValueField = "Value";
DropDownList1.DataBind();
To sort an object datasource that returns a dataset you use the Sort property of the control.
Example usage In the aspx page to sort by ascending order of ColumnName
<asp:ObjectDataSource ID="dsData" runat="server" TableName="Data"
Sort="ColumnName ASC" />
is better if you sort the Source before Binding it to DropDwonList.
but sort DropDownList.Items like this:
Dim Lista_Items = New List(Of ListItem)
For Each item As ListItem In ddl.Items
Lista_Items.Add(item)
Next
Lista_Items.Sort(Function(x, y) String.Compare(x.Text, y.Text))
ddl.Items.Clear()
ddl.Items.AddRange(Lista_Items.ToArray())
(this case i sort by a string(the item's text), it could be the suplier's name, supplier's id)
the Sort() method is for every List(of ) / List<MyType>, you can use it.
You can do it this way is simple
private void SortDDL(ref DropDownList objDDL)
{
ArrayList textList = new ArrayList();
ArrayList valueList = new ArrayList();
foreach (ListItem li in objDDL.Items)
{
textList.Add(li.Text);
}
textList.Sort();
foreach (object item in textList)
{
string value = objDDL.Items.FindByText(item.ToString()).Value;
valueList.Add(value);
}
objDDL.Items.Clear();
for(int i = 0; i < textList.Count; i++)
{
ListItem objItem = new ListItem(textList[i].ToString(), valueList[i].ToString());
objDDL.Items.Add(objItem);
}
}
And call the method this SortDDL(ref yourDropDownList);
and that's it. The data in your dropdownlist will be sorted.
see http://www.codeproject.com/Articles/20131/Sorting-Dropdown-list-in-ASP-NET-using-C#
You can use this JavaScript function:
function sortlist(mylist)
{
var lb = document.getElementById(mylist);
arrTexts = new Array();
arrValues = new Array();
arrOldTexts = new Array();
for(i=0; i<lb.length; i++)
{
arrTexts[i] = lb.options[i].text;
arrValues[i] = lb.options[i].value;
arrOldTexts[i] = lb.options[i].text;
}
arrTexts.sort();
for(i=0; i<lb.length; i++)
{
lb.options[i].text = arrTexts[i];
for(j=0; j<lb.length; j++)
{
if (arrTexts[i] == arrOldTexts[j])
{
lb.options[i].value = arrValues[j];
j = lb.length;
}
}
}
}
Try This:
/// <summary>
/// AlphabetizeDropDownList alphabetizes a given dropdown list by it's displayed text.
/// </summary>
/// <param name="dropDownList">The drop down list you wish to modify.</param>
/// <remarks></remarks>
private void AlphabetizeDropDownList(ref DropDownList dropDownList)
{
//Create a datatable to sort the drop down list items
DataTable machineDescriptionsTable = new DataTable();
machineDescriptionsTable.Columns.Add("DescriptionCode", typeof(string));
machineDescriptionsTable.Columns.Add("UnitIDString", typeof(string));
machineDescriptionsTable.AcceptChanges();
//Put each of the list items into the datatable
foreach (ListItem currentDropDownListItem in dropDownList.Items) {
string currentDropDownUnitIDString = currentDropDownListItem.Value;
string currentDropDownDescriptionCode = currentDropDownListItem.Text;
DataRow currentDropDownDataRow = machineDescriptionsTable.NewRow();
currentDropDownDataRow["DescriptionCode"] = currentDropDownDescriptionCode.Trim();
currentDropDownDataRow["UnitIDString"] = currentDropDownUnitIDString.Trim();
machineDescriptionsTable.Rows.Add(currentDropDownDataRow);
machineDescriptionsTable.AcceptChanges();
}
//Sort the data table by description
DataView sortedView = new DataView(machineDescriptionsTable);
sortedView.Sort = "DescriptionCode";
machineDescriptionsTable = sortedView.ToTable();
//Clear the items in the original dropdown list
dropDownList.Items.Clear();
//Create a dummy list item at the top
ListItem dummyListItem = new ListItem(" ", "-1");
dropDownList.Items.Add(dummyListItem);
//Begin transferring over the items alphabetically from the copy to the intended drop
downlist
foreach (DataRow currentDataRow in machineDescriptionsTable.Rows) {
string currentDropDownValue = currentDataRow["UnitIDString"].ToString().Trim();
string currentDropDownText = currentDataRow["DescriptionCode"].ToString().Trim();
ListItem currentDropDownListItem = new ListItem(currentDropDownText, currentDropDownValue);
//Don't deal with dummy values in the list we are transferring over
if (!string.IsNullOrEmpty(currentDropDownText.Trim())) {
dropDownList.Items.Add(currentDropDownListItem);
}
}
}
This will take a given drop down list with a Text and a Value property of the list item and put them back into the given drop down list.
Best of Luck!
If you are adding options to the dropdown one by one without a dataset and you want to sort it later after adding items, here's a solution:
DataTable dtOptions = new DataTable();
DataColumn[] dcColumns = { new DataColumn("Text", Type.GetType("System.String")),
new DataColumn("Value", Type.GetType("System.String"))};
dtOptions.Columns.AddRange(dcColumns);
foreach (ListItem li in ddlOperation.Items)
{
DataRow dr = dtOptions.NewRow();
dr["Text"] = li.Text;
dr["Value"] = li.Value;
dtOptions.Rows.Add(dr);
}
DataView dv = dtOptions.DefaultView;
dv.Sort = "Text";
ddlOperation.Items.Clear();
ddlOperation.DataSource = dv;
ddlOperation.DataTextField = "Text";
ddlOperation.DataValueField = "Value";
ddlOperation.DataBind();
This would sort the dropdown items in alphabetical order.
If you are using a data bounded DropDownList, just go to the wizard and edit the bounding query by:
Goto the .aspx page (design view).
Click the magic Arrow ">"on the Dropdown List.
Select "Configure Data source".
Click Next.
On the right side of the opened window click "ORDER BY...".
You will have up two there field cariteria to sort by. Select the desired field and click OK, then click Finish.
You may not have access to the SQL, but if you have the DataSet or DataTable, you can certainly call the Sort() method.