I am trying to set a value for DataGridViewRow.Tag
when data binding but I don't know how to do it?
I tried with DataRow row = table.NewRow();
But row doesn't have tag.
How to set a value for DataGridViewRow.Tag when binding DataGridView
to table (for example)? Or it isn't possible?
Edit1:
Here is the code i am using:
var table = new DataTable(); table.Columns.Add("Title", typeof(string)); table.Columns.Add("URL", typeof(string)); table.Columns.Add("Read Later", typeof(bool)); foreach (XElement node in nodes) { Helper.CheckNode(node); var id = node.Attribute("id").Value; var url = node.Element("path").Value; var comment = node.Element("title").Value; var readlater = node.Attribute("readLater")?.Value.ToString() == "1"; var row = table.NewRow(); row.ItemArray = new object[] { url, comment, readlater }; table.Rows.Add(row);//Edit2 } dataGridView1.DataSource = table;
I am trying to set a tag for the row to use it in CellClick event:
var cRow = dataGridView1.Rows[e.RowIndex]; var id = cRow.Tag.ToString();
Separate the data from how it is displayed
When using a DataGridView, it is seldom a good idea to access the cells and the columns directly. It is way more easier to use
DataGridView.DataSource
.In modern programming there is a tendency to separate your data (= model) from the way your data is displayed (= view). To glue these two items together an adapter class is needed, which is usually called the viewmodel. Abbreviated these three items are called MVVM.
Use DataGridView.DataSource to display the data
Apparently, if the operator clicks a cell, you want to read the value of the tag of the row of the cell, to get some extra information, some Id.
This displayed row is the display of some data. Apparently part of the functionality of this data is access to this Id. You should not put this information in the view, you should put it in the model.
Apparently you have a method to fetch the data that you want to display from a sequence of
nodes
. Separate fetching this data (=model) from displaying it (= view):I don't know what is in node "ReadLater", apparently you know how to convert it to a Boolean.
For every property that you want to display you create a DataGridViewColumn. Property DataPropertyName defines which property should be shown in the column. Use DefaultCellStyle if a standard ToString is not enough to display the value properly, for instance, to define the number of digits after the decimal point, or to color negative values red.
You can do this using the visual studio designer, or you can do this in the constructor:
You don't want to display the Id, so there is no column for this.
Now to display the data, all you have to do is assign the list to the datasource:
This is display only. If the operator can change the displayed values, and you want to access the changed values, you should put the items in an object that implements interface IBindingList, for instance, using class (surprise!)
BindingList<T>
:Initialization:
And presto! All webpages are displayed. Every change that the operator makes: add / remove / edit rows are automatically updated in the DisplayedWebPages.
If you want to access the currently selected WebPages:
Now apparently whenever the operator clicks a cell, you want to do something with the Id of the WebPage that is displayed in the Row of the cell.
React on Cell Click: get the Id
We've handled the View above. ViewModel is the event handler:
ProcessWebPage is typically a method in your Model class:
Conclusion: advantages of separating model from view
By the way, did you see that all ViewModel methods are one-liners? Only your Model methods
FetchWebPages
and ProcessWebPage contain several lines.Because you separated the View from the Model, changes to your Model or your View will be fairly simple: