I've RadGrid where I want to add a column dynamically so I've done something like this in page load
GridTemplateColumn gtc = new GridTemplateColumn();
gtc.DataField = "chqNumber";
gtc.HeaderText = "Cheque Number";
gtc.UniqueName = "chqNumber";
RadGrid1.MasterTableView.Columns.Add(gtc);
It work fine, now I want to add textbox in this column as the user click "+add new record" on grid here is my code of itemCreated event
GridEditableItem gdit = (GridEditableItem)e.Item;
RadTextBox txtBox = new RadTextBox();
txtBox.ID = "someIDWhatEver";
gdit["chqNumber"].Controls.Add(txtBox);
but this textbox gets added to another new column what I mean is this textbox does not added to same chqNumber column you can view my attached image which will illustrate better
as you can see my dynamic column gets added at the last even after insert and cancel button and dynamic textbox doesn't gets in this column please avoid my english grammatical mistakes :P
Related
I currently have an event set for RowHeaderMouseClick when I click on the header, my textbox is populated with data from the DataGrid. I want to make my textbox populate when I select the row instead of the header. Ideally, I want to hide the header. What is the correct event/property that I need to set to achieve this?
Edit:
Attaching screenshot
You can make like this for any event
//Handle RowChanged.
table.RowChanged += table_RowChanged;
//RowChanged Event.
static void table_RowChanged(object sender, DataRowChangeEventArgs e)
{
Console.WriteLine("... Changed: " + (int)e.Row["Dosage"]);
}
You don't need to do it with events, as you seem to be saying that the textbox gets populated with an item from the row. In such a case you would have:
your datagridview bound to a bindingsource
your bindingsource bound to a datatable or other list that supports binding
your textbox's text property bound to the same bindingsource
Every time the user clicks a row in the grid (or uses the keyboard to move to another row) they are causing the Current property of the bindingsource to update. This in turn changes any of the textboxes that are bound to true same binding source (a textbox only shows the current row item to which it is bound)
For a quick demo of how this works, do these steps (apologies I can't make any screenshots - I'm on a cellphone) - skip any steps you've already done
add a DataSet type file to your project
open it and right click the surface, add a datatable and name it eg Person
right click it and add a couple of columns eg FirstName and LastName
save
switch to the form
open the Dat Sources window (view menu, other windows)
drag the Person node to the form, a datagridview appears as well as some other stuff (bindingsource) - look at the DataSource property of the grid
in the Data sources window again click the drop down button next to Person, change it to details
drag the person node to the form again, this time textboxes appear; take a look at their Text bindings in the (data bindings) section of their properties - they're bound to the same bindingsource as the grid is
run the project, type 4 names into the grid and then select different rows at random using the mouse; the textboxes update to stay current with the grid selection
If this isn't the way you've done things up to now you should consider making it the way; using the DataSet designer to create strongly typed datatables is an easy way to model the data aspects of your program and there is a lot of tooling set up to make life easier when you use them to make a data driven app. If you've been putting data directly into a datagridview it's something you should avoid going forward, and instead separate your concerns in a more mvc style pattern
If you want to remove or make the rowHeader invisible
You can SET an Event DataGridView CellClick and below is the CODE
//Im Assuming that we are getting the row VALUES
try{
int rowIndex = e.RowIndex; //getting the position of ROW in DGV when CLick
int columns = Columns.Count//numebr of Columns
for(int i=0; i< columns;i++)
{
//Here we can populate textBoxes and using FlowLayoutPanel
string values = dataGridView1.Rows[rowIndex].Columns[i].Value.toString();
//Creating new TextBox
TextBox txtBox = new TextBox();
txtBox.Text = values;
txtBox.Size = new Size(100,200);
flowLayoutPanel1.Controls.Add(txtBox);
}
}catch(Exception ee){}
OR If you want to pass the VALUES of the selected ROW you can do like this
textBox.Text = dataGridView1.Rows[rowIndex].Columns[0].Value.toString();//1st col
textBox1.Text = dataGridView1.Rows[rowIndex].Columns[1].Value.toString();//2nd col
First, right-click your dataGrid and select properties
Then change the SelectionMode to FullRowSelect if you like as shown below:
Next, In the datagrid event section double-click on SelectionChanged
and write code like this, you can use other events, although
// Just for example
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
try
{
if (dataGridView1.CurrentRow != null && dataGridView1.CurrentRow.Index >= 0)
{
var row = dataGridView1.CurrentRow;
txtCode.Text = (row.Cells["code"].Value != null) ? row.Cells["code"].Value.ToString() : string.Empty;
txtFirstName.Text = (row.Cells["firstName"].Value != null) ? row.Cells["firstName"].Value.ToString() : string.Empty;
txtLastName.Text = (row.Cells["lastName"].Value != null) ? row.Cells["lastName"].Value.ToString() : string.Empty;
}
}
catch { }
}
Good afternoon.
I am attempting to create a DropDownList populated in 2 ways:
The options are from an Enumeration, listing each possible option.
The selected value is from a database table.
The DropDownList's SelectedIndexChanged takes care of updating the database for me.
Note that the control is working already, but I think I'm not understanding the lifecycle correctly and would like some clarification.
On PageInit, I generate a Table with Headers and one of the cells having my DropDownList.
//Essentially an ArrayList with "row" information (it uses a Field class with
//several parameters, each corresponding to 1 column in the table
GenericFieldsCollection data = new GenericFieldsCollection();
data.FillFieldList();
Table TableToEdit = new Table();
TableHeaderCell Header_FieldName = new TableHeaderCell();
(...)
foreach (GenericField row in data.FieldList)
{
(...)
//The cell with the DDL:
TableCell Column_GraphName = new TableCell();
Column_GraphName.Controls.Add(GenerateGraphSelectionDropdown());
(...)
}
Obviously, if I do not generate it here, the Click events won't work.
This procedure only queries the database with a Select, no updates are made.
After the first (!PostBack) call, subsequent calls can be triggered by changing the DropDownList's index (it has AutoPostBack=true).
So, my PageInit runs again, as expected. And, after Load Number 15 in here happens (
OnXXX (control event)), and my database gets updated.
Later in the Cycle (OnPreRender), I tried clearing the Div anchor I'm using for this table of all controls, and call my GenerateFieldCollectionTable() again. Since my update query in my DropDownList's SelectedIndexChanged event has already executed, I expected to see the updated values. However, doing this will show the old value, and wreck the behaviour (I won't be able to change anything and there is no change in the database).
After a bit of testing, I found out that Page_PreRender having this line is the issue:
------> //TableToEditGraphFields.Controls.Clear();
GenerateFieldCollectionTable();
Clearing the controls of TableToEditGraphFields, an action that happens AFTER CLICK EVENTS (since
Control.OnPreRender is #22 and OnSelectedIndexChanged is #15), means that on the next PostBack the Controls won't trigger click events, as they've been cleared. Is there a part of the cycle where I can process the Click event, rebuild the controls, and still have them clickable on the next PostBack?
Thank you in advance.
EDIT: Code that generates the table:
GenericFieldsCollection data = new GenericFieldsCollection();
data.FillFieldList();
Table TableToEdit = new Table();
TableToEdit.CssClass = "table";
TableRow Headers = new TableRow();
TableHeaderCell Header_FieldName = new TableHeaderCell();
Header_FieldName.Text = "Field Name";
Headers.Cells.Add(Header_FieldName);
//Repeat for each header
TableToEdit.Rows.Add(Headers);
foreach (GenericField row in data.FieldList)
{
TableRow currentRow = new TableRow();
//Repeat for each column; example with the "Order" column
TableCell Column_Order = new TableCell();
TextBox editableOrder = new TextBox();
editableOrder.Attributes.Add("FieldName", row.Name);
editableOrder.Attributes.Add("FieldTable", row.Table);
editableOrder.AutoPostBack = true;
editableOrder.TextChanged += EditableOrder_TextChanged;
editableOrder.Text = row.Order.ToString();
Column_Order.Controls.Add(editableOrder);
currentRow.Cells.Add(Column_Order);
TableToEdit.Rows.Add(currentRow);
}
TableToEditGraphFields.Controls.Add(TableToEdit);
" I'm not understanding the lifecycle correctly and would like some clarification."
How does the life cycle work?
As you can see in the picture below. This is how the life cycle is working.
All the information is from codedisplay There is a lot more information for you to read.
I want to add a button on GridView cell on certain condition.
I did the following in RowDatabound event
if( i==0)
{
Button btn= new Button();
btn.Text = "view more";
e.Row.Cells[7].Controls.Add(btn);
}
When this executes, the text in the cell which is bound is lost and only the button appears.
I need to have the button along with the cell text present already.
Can anyone please help me doing this?
When you add a control into the cell it trumps the text in the cell and only wants to display the control(s).
You can however have both the text and the button while keeping them separate. To do this you need to add another control in the form of a label:
Label myLabel = new Label();
myLabel.Text = e.Row.Cells[7].Text; //might want to add a space on the end of the Text
e.Row.Cells[7].Controls.Add(myLabel);
LinkButton myLinkButton = new LinkButton();
myLinkButton.Text = "view more";
e.Row.Cells[7].Controls.Add(myLinkButton);
It's a workaround, check if it helps you:
You can convert your existing BoundColumn to Linkbuton if it is feasible with your requirement.
if( i==0)
{
LinkButton lnkbtn = new LinkButton();
lnkbtn.Text = e.Row.Cells[7].Text;
// Create a command button and link it to your id
// lnkbtn.CommandArgument = e.Row.Cells[0].Text; --Your Id
// lnkbtn.CommandName = "NumClick";
// btn.Text = "view more";
e.Row.Cells[7].Controls.Add(lnkbtn);
}
You have to recreate all dynamic controls on every postback. But RowDataBound is executed only if the grid gets databound. So this is not the right approach.
If this is just a single button you should add it declaratively to the aspx in a TemplateField. Then you can switch visibility in RowDataBound.
Tutorial 12: Using TemplateFields in the GridView Control
Button btn = (Button)e.Row.FindControl("ButtonID");
btn.Visible = i==0;
You can handle the Click event of the Button for your "view more"-logic.
I pull results from Oracle database and store it in DataTable before setting it as source in DataGridView. The reason for this is I remove some columns before I show it to user. Using DataGridViewButtonColumn I have added column that has enables user to "Edit" specific row. My problem is I'm trying to disable that button based on value in that current row. Leave the rest of the row buttons enabled.
var table = OracleConnection.Results(myquery);
table.Columns.Remove("Comments");
var editButton = new DataGridViewButtonColumn;
editButton.Value = "Edit";
editButton.Text = "Edit";
editButton.UseColumnTextForButtonValue = true;
_dtgvResults.Source = table;
_dtgvResults.Columns.Add(editButton);
Take a look in OnRowDataBound event in your DataGridView
MS Reference
How do you add a button to cells in a row and not the entire column in a datagridview?
I think Adrian's answer was close. Try something like this.
if ((string)table.Rows[0].Cells[0].Value == "I should be a button") {
// you can add formatting or values to the button before assigning it here
table.Rows[0].cells[0] = new DataGridViewButtonCell();
}
I think the best answer if found here:
Hide gridview button. All you need to do is to add a DataGridViewButtonCell where you want buttons, and DataGridViewTextBoxCell where you do not. The column has to be DataGridViewButton type.
See this similar post in SO, probably helps
adding control to gridview
In case Win Form, Check this MSDN post
Column Types in the Windows Forms DataGridView Control
OR this code project post ... though it gives example of adding a image button
DataGridView Image Button Cell
#tmax In that case you can probably put your button creation code in GridView_RowCreated event like below
void GridView_RowCreated(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.Header)
{
//Button creation code here
}
}
private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
Button btn = new Button();
//btn attributes
dataGridView1.Rows[0].Cells[3].Value = new Button();
}
try something like this.
What I endded up doing was stacking a DataGridView on top of another one. I turned off the border, gridlines, and scrollbars. Then create dynamic button columns to match the main datagridview with only one row of buttons. Then I used the ColumnWidthChanged event handler to resize both the DataGridViews together. Anyway's this was my workaround for now.
DataGridViewButtonColumn dataGridViewButtonColumn = new DataGridViewButtonColumn();
dataGridViewButtonColumn.Name = "Select";
dataGridViewButtonColumn.HeaderText = "Select";
dataGridViewButtonColumn.ReadOnly = false;
dataGridView1.Columns.Add(dataGridViewButtonColumn);
After assigning data source to gridviewCTRL. you can add new column with button with below code.
DataGridViewButtonColumn startbtn = new DataGridViewButtonColumn();
startbtn.Name = "Action";
startbtn.Text = "Start";
startbtn.UseColumnTextForButtonValue=true;
int columnIndex = 6;
gridviewCTRL.Columns.Insert(columnIndex, startbtn);
This will add the button to each and every row at define column index.
if you want to render condition the AccessibleObject, then you can do something similar to below.
foreach (DataGridViewRow rowdata in gridviewCTRL.Rows)
{
// this is just an example in my case i am checking a previous column value
if (rowdata.Cells[5].Value=="XYZ")
{
rowdata.Cells[6] = new DataGridViewTextBoxCell();
}
}
This way you can dynamically render/ showing the control in the GridView in Winforms c#.
The above code simple update the cell with new cell. We can't remove button from the cell nor remove whole, so instead we can initial a new cell that will override the button visibility.
I am not sure if this will help but you can also consider using TableLayoutPanel.
Refer: Winforms TableLayoutPanel adding rows programmatically