Set SelectedValue of GridDropDownColumn - c#

I'm trying to set the value of a GridDropDownColumn in my RadGrid.
Note that my GridDropDownColumn is not in a template, just part of <columns>.
I'm using the InsertCommand event to do this as my whole experiment is around manipulating data in there.
Frontend:
<telerik:RadGrid ID="RadGrid1" runat="server">
<MasterTableView>
<Columns>
<telerik:GridDropDownColumn DataSourceID="MySource" DataField="RowId" UniqueName="RowId" ListValueField="id" ListTextField="Name" SortExpression="RowId" HeaderText="RowId" />
</Columns>
</MasterTableView>
</telerik:RadGrid>
Backend:
protected void RadGrid1_InsertCommand(object sender, GridCommandEventArgs e) {
if (e.Item is GridEditFormItem && e.Item.IsInEditMode) {
GridEditFormItem editItem = (GridEditFormItem)e.Item;
DropDownList list = (DropDownList)editItem["GridDropDownColumn"].Controls[0];
list.SelectedValue = HiddenFieldIdToSave.Value;
}
}
This is giving me a rather nasty error though.
Unhandled exception at line 15, column 16485 in http://localhost:55555/Telerik.Web.UI.WebResource.axd?_TSM_HiddenField_=RadScriptManager1_TSM&compress=1&_TSM_CombinedScripts_=;;System.Web.Extensions,+Version=4.0.0.0,+Culture=neutral,+PublicKeyToken=31321323135:en-N:5924cf72drgdrg-a608a92942c5:ea597d4b:b25378d2;Telerik.Web.UI,+Version=2014.2.724.45,+Culture=neutral,+PublicKeyToken=121fae781awdawggcvb31-d2d2285652a6:fghfghfghf:58366029
0x800a139e - JavaScript runtime error: Sys.WebForms.PageRequestManagerServerErrorException: Cannot find cell bound to column with unique name 'GridDropDownColumn'

In your backend C#, you're trying to access a column named GridDropDownColumn, but instead you should be using the row's UniqueName property, which you've set as RowId. Try this:
protected void RadGrid1_InsertCommand(object sender, GridCommandEventArgs e)
{
if (e.Item is GridEditFormItem && e.Item.IsInEditMode)
{
GridEditFormItem editItem = (GridEditFormItem)e.Item;
// Use the column's unique name as the accessor:
DropDownList list = (DropDownList)editItem["RowId"].Controls[0];
list.SelectedValue = HiddenFieldIdToSave.Value;
}
}

I found out why i was getting this error.
I had 2 dropdown lists which both hooked up on the same datasource, this caused a false value to be passed, this then caused my Insert/Update DataObjectMethod to fire the error.
Also my example was looking at the wrong UniqueName.

Related

How can I programatically find and expand a particular row in a Telerik RadGrid?

How can one achieve the following requirement?
Based on values in the queryString, the requested record must be expanded into its DetailView.
This example uses Entity Framework 6 for accessing data. This means the RadGrid's pageSize, pageIndex and sort information must persist within the call EF makes to the database.
Let's assume the following URL when you arrive at the page containing the RadGrid.
http://localhost:61878/search?pageindex=8&orderid=2871517&pagesize=50
The RadGrid declarative markup would look like this.
<telerik:RadGrid ID="OrdersMasterGrid" runat="server"
AllowPaging="True"
AllowSorting="True"
AutoGenerateColumns="False"
OnNeedDataSource="GridOnNeedDataSource"
OnPreRender="GridPreRender">
Then the PageLoad would look like this. This fires BEFORE the RadGrid's OnNeedDataSource event so it's important to set the correct pageindex and pagesize because that information will flow all the way to the database.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
OrderID_QueryString = Request.QueryString.GetValue<string>("orderid");
OrdersMasterGrid.MasterTableView.CurrentPageIndex = Request.QueryString.GetValue<int>("pageindex");
OrdersMasterGrid.MasterTableView.PageSize = Request.QueryString.GetValue<int>("pagesize");
}
Programatically expanding the correct row takes place during the OnPreRender event.The GridPreRender eventHandler would look like:
protected void GridPreRender(object sender, EventArgs e)
{
foreach (object gridDataItem in OrdersMasterGrid.MasterTableView.Items)
{
if (gridDataItem is GridDataItem)
{
GridDataItem gdi = gridDataItem as GridDataItem;
if (gdi["OrderID"].Text == OrderID_QueryString)
{
gdi.Expanded = true;
break;
}
}
}
}
Conclusion: Although this example uses the queryString, it might be better to use ViewData, ViewBag or other transparent mechanisms. The pitfall of this approach is if the user decides to bookmark the page, it's going to stop working eventually when the requested orderid does not exist in the data returned by EF6 for the 8th page when pagesize is 50.

Error: Calling dropdownlist in ItemTemplate

I have this code below. I just want to call/use the dropdown list but it is inside a item template. As I run the code, I encountered an error. Please help me.
<EditItemTemplate>
<asp:DropDownList ID="statusDDL" runat="server" AutoPostBack="True"
onselectedindexchanged="statusDDL_SelectedIndexChanged">
</asp:DropDownList>
</EditItemTemplate>
protected void statusDDL_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList ddlStatus = new DropDownList();
ddlStatus = auditGridView.FindControl("statusDDL") as DropDownList;
if (ddlStatus.SelectedItem.Text == "Closed")
{
//do logic here
}
}
Im encountering an error: object reference not set to an instance of the object. WHY? I already declared the dropdown list as shown in the code above.
You can use the sender in the SelectedIndexChanged event handler:
protected void statusDDL_SelectedIndexChanged(object sender, EventArgs e)
{
if ((sender as DropDownList).SelectedItem.Text == "Closed")
{
//do logic here
}
}
However, this is rather Winform style programming. Using WPF you should really look into data binding. But as you are using asp:DropDownList I'm not sure it's WPF?

Object reference not set to an instance of an object when tring to set the selection of a combo box

I have a text box and a RadComboBox like this :
<asp:TextBox ID="txt_inner_emp_num" runat="server" Width="60px"
ontextchanged="txt_inner_emp_num_TextChanged" AutoPostBack="true"></asp:TextBox>
<telerik:RadComboBox ID="rad_ddl_inner_emp_name" runat="server" CausesValidation="False"
CollapseDelay="0" Culture="ar-EG" ExpandDelay="0" Filter="Contains" ItemsPerRequest="100"
MarkFirstMatch="true" Width="380px" EnableAutomaticLoadOnDemand="True" EmptyMessage="-emp name-" ShowMoreResultsBox="True" AutoPostBack="True">
</telerik:RadComboBox>
According to the Telerik Documentation
Set a data source to the RadComboBox. Use either DataSourceID or the
DataSource property to do this and set the DataTextField and
DataValueField properties to the respective fields in the data source.
(Note that when using DataSource you must set the property on each
postback, most conveniently in Page_Init.) Set
EnableAutomaticLoadOnDemand to true.
protected void BindEmployees()
{
rad_ddl_inner_emp_name.Items.Clear();
rad_ddl_inner_emp_name.DataSource = Utilities.GetAllEmployees();
rad_ddl_inner_emp_name.DataTextField = "name";
rad_ddl_inner_emp_name.DataValueField = "emp_num";
rad_ddl_inner_emp_name.DataBind();
}
protected void Page_Init(object sender, EventArgs e)
{
BindEmployees();
}
protected void txt_inner_emp_num_TextChanged(object sender, EventArgs e)
{
rad_ddl_inner_emp_name.ClearSelection();
rad_ddl_inner_emp_name.Items.FindItemByValue(txt_inner_emp_num.Text.TrimEnd()).Selected = true;//Get exception here Object reference not set to an instance of an object.
}
I find rad_ddl_inner_emp_name.Items.Count = 0 !! before set the selection ! How to fix this problem ?
As I'm sure you aware of by now, the radcombox typeahead functionality searches text via client side interaction and not by value, which is why you can't find the values.
What I would suggest is having a secondary object to search by emp_num (assuming that's the value that will always be entered into the textbox).
For example, create a global variable:
private Dictionary<string, string> Emp_Dict = new Dictionary<string, string>();
Then populate this dictionary when you do your binding. The following code assumes an ienumerable type being returned. If not you may have to populate the dictionary differently. Also, for this to work, you have to include (System.Linq).
var dataSource = Utilities.GetAllEmployees();
Emp_Dict = dataSource.ToDictionary(ex => ex.emp_num, ex => ex.name);
rad_ddl_inner_emp_name.Items.Clear();
rad_ddl_inner_emp_name.DataSource = dataSource;
rad_ddl_inner_emp_name.DataTextField = "name";
rad_ddl_inner_emp_name.DataValueField = "emp_num";
rad_ddl_inner_emp_name.DataBind();
So now we need to use the dictionary on the text changed event.
protected void txt_inner_emp_num_TextChanged(object sender, EventArgs e)
{
rad_ddl_inner_emp_name.ClearSelection();
if (Emp_Dict.ContainsKey(txt_inner_emp_num.Text.TrimEnd()))
{
rad_ddl_inner_emp_name.SelectedValue = txt_inner_emp_num.Text.TrimEnd();
rad_ddl_inner_emp_name.Text = Emp_Dict[txt_inner_emp_num.Text.TrimEnd()];
}
}
Now when the text changes in the text box, the radcombobox will update when a valid emp_num is entered into the textbox.
The Problem is that the Items only get loaded when you request them!
Set
EnableAutomaticLoadOnDemand="False"
and it will work!
UPDATE:
if you want to use LoadOnDemand set these two Properties and delete the EnableAutomicLoadOnDemand!
EnableLoadOnDemand="True"
EnableItemCaching="True"
UPDATE 2:
Enable ItemCaching isn´t necessary, but it doesn´t hurt!
You do not need to bind data to RadComboBox on every postback unless you disable the view state.
Filter, MarkFirstMatch and EnableAutomaticLoadOnDemand are not useful in your case as you are loading all employees by yourself.
LoadOnDemand basically is when user starts typing inside ComboBox, ComboBox fires ItemsRequested event and retrieves data via ajax.
<asp:TextBox ID="txt_inner_emp_num" runat="server" Width="60px"
ontextchanged="txt_inner_emp_num_TextChanged" AutoPostBack="true" />
<telerik:RadComboBox ID="rad_ddl_inner_emp_name" runat="server"
CausesValidation="False" Culture="ar-EG">
</telerik:RadComboBox>
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack)
{
rad_ddl_inner_emp_name.DataSource = Utilities.GetAllEmployees();
rad_ddl_inner_emp_name.DataTextField = "name";
rad_ddl_inner_emp_name.DataValueField = "emp_num";
rad_ddl_inner_emp_name.DataBind();
}
}
protected void txt_inner_emp_num_TextChanged(object sender, EventArgs e)
{
string value = txt_inner_emp_num.Text;
if(!string.IsNullOrWhiteSpace(value))
{
value = value.Trim();
if (rad_ddl_inner_emp_name.Items
.FindItemByValue(txt_inner_emp_num.Text.Trim()) != null)
rad_ddl_inner_emp_name.SelectedValue = value;
}
}
Since you don't have any item in rad_ddl_inner_emp_name.Items you can set txt_inner_emp_num.Text as selected in ddl.
First check if rad_ddl_inner_emp_name.Items count > 0 then set desired text selected. Or you can check if rad_ddl_inner_emp_name.Items.FindItemByValue(txt_inner_emp_num.Text.TrimEnd()) is not null.

How to change combobox in item template with respect to the data coming from code behind or data source in DataGrid

I have a data grid, and data is coming from database, it has combo boxes in status and I want them to be according to their respective values, for example, there is a column of status, it has a combo box: Open and Close, I want it to be changed with respect to the value it has in database table-column, if it has Close written in database table column, combo box should be selected as Close, if it has Open then it should be selected as Open. Please see the image attached.
Thanks for Help in advance.
Assuming that you're using a template column, you can do this:
<asp:TemplateColumn>
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" SelectedValue='<%# Eval("DropDownValueColumn") %>' />
</ItemTemplate>
</asp:TemplateColumn>
If you want to set the SelectedValue in the ItemDataBound event, you can do it like this:
protected void DataGrid1_ItemDataBound(object sender, GridItemEventArgs e)
{
DropDownList ddl = e.Item.FindControl("DropDownList1") as DropDownList;
if (ddl != null)
{
ddl.SelectedValue = DataBinder.Eval(e.Item.DataItem, "DropDownColumnValue").ToString();
}
}
First of all save your data source in viewstate. If datasource is datatable then do like this.
protected void gridview1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddlList = (DropDownList)e.Row.FindControl("Name_of_DPList");
int i=e.Row.RowIndex;
DataTable dtTable = (DataTable)ViewState["dtPurchaseOrder"];
string str = dtTable.Rows[i]["Name_Of_column"].ToString();//Name of the column in data source that stores the status.
ddlList.items.FindByText(str).Selected=true;
}
}

How can I access DataGridRow from a textbox on that row?

In a DataGrid, when text in a textbox changes I want to add the value of another field in that row to an array.
public void txtTitle_TextChanged(object sender, EventArgs e)
{
TextBox titleBox = (TextBox)sender;
DataGridItem myItem = (DataGridItem)titleBox.Parent.Parent;
string test = DataBinder.Eval(myItem.DataItem, "prod_id").ToString();
}
However myItem.DataItem evaluates as null. I was expecting it to evaluate as DataRowView?
You can get the TextChanged event to fire if you do the following:
<asp:DataGrid ID="DataGrid1" runat="server" AutoGenerateColumns="False"
onitemdatabound="DataGrid1_ItemDataBound">
<Columns>
<asp:TemplateColumn HeaderText="Test">
<ItemTemplate>
<asp:TextBox OnTextChanged="txtBox_TextChanged" ID="TextBox1" runat="server" AutoPostBack="True"></asp:TextBox>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="Name" HeaderText="Test 1"></asp:BoundColumn>
</Columns>
</asp:DataGrid>
You will notice that i have the following properties set:
AutoPostBack="True"
I have also manually added the OnTextChanged="txtBox_TextChanged" to the text box as well.
In my code behind i have:
protected void txtBox_TextChanged(object sender, EventArgs e)
{
TextBox txtBox = (TextBox)sender;
Label1.Text = txtBox.Text;
}
The only way the event will fire is when you lose focus on the text box after typing.
Key points to consider:
This will cause a post back, so Ajax might be a good way to keep the user experience nice.
You will need to make sure you wrap your DataBind() in a if (!IsPostBack)
Hope this helps!
Effectively, I solved this by adding an autonumber column to the table, and using the value of this to determine the row's positino in the table, then using the value of this to affect the appropriate row in the datagrid.
I'm now merely changing the color of the row rather than adding values in that row to an array, as stated in the original question.
public void txtPrice_TextChanged(object sender, EventArgs e)
{
TextBox txtPrice = (TextBox)sender;
DataGridItem myItem = (DataGridItem)txtPrice.Parent.Parent;
markRows(myItem, true);
}
public void markRows(DataGridItem myItem, bool toSave)
{
// Prepeare to save this record?
CheckBox thisSave = (CheckBox)myItem.FindControl("chkSave");
thisSave.Checked = toSave;
// Establish the row's position in the table
Label sNo = (Label)myItem.FindControl("SNo");
int rowNum = Convert.ToInt32(sNo.Text) - 1;
CheckBox rowSave = (CheckBox)grid.Items[rowNum].FindControl("chkSave");
// Update background color on the row to remove/add highlight
if (rowSave.Checked == true)
grid.Items[rowNum].BackColor = System.Drawing.Color.GreenYellow;
else
{
Color bgBlue = Color.FromArgb(212, 231, 247);
grid.Items[rowNum].BackColor = bgBlue;
// some code here to refresh data from table?
}
}

Categories