How to pass an repeating object to an user control into repeater - asp.net

For example I use telerik rad grid, and bind list of users to it
rgUsers.DataSource = GetUsersList();
rgUsers.DataBind();
I have user control UserEditor that receives User object,
<radG:RadGrid runat="server" ID="rgUsers">
<MasterTableView>
<Columns>
<radG:GridTemplateColumn>
<ItemTemplate>
<asp:Label runat="server" ID="lblName" Text='<%# Eval("username") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<uc:UserEditor ID="UserEditor" runat="server" User='???????' />
</EditItemTemplate>
</radG:GridTemplateColumn>
...
Can I pass an User object to the UserEditor, or I must to make it in Data Binding event?

I think it works like native ASP.NET controls:
RadControls for ASP.NET AJAX Documentation - Event sequence
<radG:RadGrid runat="server" ID="rgUsers" OnItemDataBound="rgUsers_ItemDataBound">
protected void rgUsers_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item.ItemType == GridItemType.EditItem)
{
User user = (User)e.Item.GridDataItem;
UserEditor userEditor = (UserEditor )e.Item.FindControl("UserEditor");
UserEditor.User = user;
}
}

Related

Why does GridView inside a Repeater (or other similar controls) has the event PageIndexChanging as NOT IMPLEMENTED

Simply I want to know WHY!
Is it the DataSource Type of the GridView? or the Repeater inner implementation?
The error text:
The GridView 'grdArticles' fired event PageIndexChanging which wasn't handled.
Here's the Markup code, I think it's familiar enough for everyone.
<asp:Repeater ID="rptCategories" DataSourceID="ldsCategories" runat="server">
<ItemTemplate>
<asp:GridView runat="server" ID="grdArticles" AllowPaging="true" GridLines="None" DataKeyNames="id" AutoGenerateColumns="false" DataSource='<%# Eval("Articles") %>'>
<Columns>
<asp:TemplateField ShowHeader="false" ItemStyle-Width="100%" FooterStyle-Width="100%">
<ItemTemplate>
<div class="article-menu-item">
<h1>
<asp:HyperLink ID="lnkTitle" CssClass="article-menu-title" runat="server" Text ='<%# Eval("title") %>'
NavigateUrl='<%# Vars.ArticleUrl + "?action=view&id=" + Eval("id") %>' ></asp:HyperLink>
</h1>
<!-- Date -->
<div class="article-menu-date">
<asp:Label ID="Label1" runat="server" Text='<%# Eval("date") %>'></asp:Label>
</div>
<!-- Meta Content -->
<div class="article-menu-meta">
<asp:Label ID="lblContent" runat="server" Text='<%# Bind("meta") %>'></asp:Label>
</div>
<div class="article-menu-delete">
<asp:LinkButton ID="btnDelete" Text="Delete" runat="server" OnClick="btnDelete_Click" TargetID='<%# Eval("id") %>' />
</div>
<!-- Line -->
<div style="border-bottom: 1px solid #ccc"></div>
</div>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
<p>No items to view!</p>
</EmptyDataTemplate>
</asp:GridView>
<br />
</ItemTemplate>
</asp:Repeater>
EDIT:
If I implement the OnPageIndexChanging event using the code (And modified the aspx gridview markup to handle the event):
ASPX:
<asp:GridView runat="server" ID="grdArticles" AllowPaging="true" OnPageIndexChanging="grdArticles_PageIndexChanging" GridLines="None" DataKeyNames="id" AutoGenerateColumns="false" DataSource='<%# Eval("Articles") %>'>
cs:
protected void grdArticles_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView grd = sender as GridView;
grd.PageIndex = e.NewPageIndex;
grd.DataBind();
}
Another exception thrown:
Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
Edit #2:
After following Mr #Garrison solution, and handling the Repeater itemDataBound event using the code:
protected void rptCategories_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
GridView grd = e.Item.FindControl("grdArticles") as GridView;
if (grd != null)
{
DatabaseDataClassesDataContext dc = new DatabaseDataClassesDataContext();
grd.DataSource = dc.Articles.Where(a => a.category_id == (e.Item.DataItem as Category).id);
grd.DataBind();
}
}
Got another problem: No exceptions thrown, but when navigating to another page, the GridView shows NO ROWS!!
I really think that there is an issue in the repeater core implementation!
You have two options:
Remove Paging: Set AllowPaging="false" in your GridView.
Implement Paging: Set OnPageIndexChanging="grdArticles_PageIndexChanging"
Create a method in your code behind that looks like this:
protected void grdArticles_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
grdArticles.PageIndex = e.NewPageIndex;
grdArticles.DataBind();
}
Now that we're past the first issue, let's tackle the second one. You need to handle your Repeater's ItemDataBound event. Inside there, first find your GridView with the following code:
var grdArticles = (GridView)e.Item.FindControl("grdArticles");
Now you have access to the GridView, but you've got to find the set of Articles you want to data bind to the GridView. I don't know how you're retrieving your data, so I leave that portion up to you, but once you find your list of articles to bind, use the following code:
grdArticles.DataSource = relevantArticles; // relevantArticles is a stand-in variable name, because I don't know how you're going to do it
grdArticles.DataBind();
I've figured out -with the help of others answers- that's the problem is with the DataSource type, which is -in my example- the Eval("Items"), I don't know really what's the type of it, but it's not supporting auto paging.
So, one way to step out of it -without rewriting paging logic and writing lots of code and get some mess with Sessions and querying- is to handle the ItemDataBound of the container of the GridView, I mean the Repeater or DataList, or you can handle the OnPreRender of the GridView and create the DataSource that supports the auto paging like LinqDataSource.
You may also need to handle the PageIndexChanging of the GridView like what #Garrison told us:
protected void grdArticles_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
grdArticles.PageIndex = e.NewPageIndex;
grdArticles.DataBind();
}
After that I got everything work :)

Radio list with SelectedIndexChanged not firing inside radgrid

I have a user control that contains a radio list that on SelectIndexChanged it updates a drop down.
I put together a basic page and add the user control to the page it works fine but when I move the control to inside a radgrid it doesn't work, it will post back but never call the SelectIndexChanged event.
I've pulled up 2 previous questions on this Q. 1 and Q. 2 which say that OnSelectedIndexChanged needed to be set in the aspx page. My issue is that the control doesn't exist in the aspx page and is created later so that solution does not work for me.
Working code
working.aspx
<TT:ToolTipControl ID="ToolTipEdit" runat="server" />
working.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
ToolTipEdit.getEditToolTip("POL_TERM_CD", "DataPolTermDropDownlistEdit");
}
User Control
userControl.ascx.cs
public void getEditToolTip(string fieldName, string ddlName)
{
DataPolTermRadioListBox ccPolTermRadioListBox = new DataPolTermRadioListBox(); //custom radio list
ccPolTermRadioListBox.ID = "PolTermRadioListBox";
ccPolTermRadioListBox.AutoPostBack = true;
ccPolTermRadioListBox.SelectedIndexChanged += new System.EventHandler(updateParent);
ToolTip.Controls.Add(ccPolTermRadioListBox);
}
Broken Code
brokenPage.aspx
<telerik:RadGrid ID="rgState" Skin="WebBlue" runat="server" OnNeedDataSource="rgState_NeedDataSource"
AutoGenerateColumns="False" OnPreRender="rgState_PreRender">
<MasterTableView DataKeyNames="wrtnStPolId" AllowAutomaticUpdates="false" AllowAutomaticDeletes="true"
AllowAutomaticInserts="false" CommandItemDisplay="Top" AllowMultiColumnSorting="True"
EditMode="InPlace" GroupLoadMode="Server" Caption="State(s) and Exposure(s)">
<Columns>
<telerik:GridTemplateColumn AllowFiltering="false" HeaderText="Pol Type Nstd" SortExpression="nonStdPolTypeCd"
UniqueName="nonStdPolTypeCd">
<ItemTemplate>
<asp:Label ID="lblNonStdPolTypeCd" runat="server" align="center" Text='<%#DataBinder.Eval(Container.DataItem, "nonStdPolTypeCd")%>' />
</ItemTemplate>
<EditItemTemplate>
<cc1:DataNonStdTypeCdDropDownList ID="ddlNonStdTypeCd" runat="server" ClientIDMode="Predictable">
</cc1:DataNonStdTypeCdDropDownList>
<TT:ToolTipControl ID="ttcNonStdPolTypeCdEdit" runat="server" />
</EditItemTemplate>
</telerik:GridTemplateColumn>
</Columns>
</MasterTableView>
</telerik:RadGrid>
brokenPage.aspx.cs
protected void rgState_PreRender(object sender, EventArgs e)
{
RadGrid rgExpMod = (RadGrid)sender;
foreach (GridDataItem row in rgExpMod.Items)
{
GridDataItem gdiItem = (GridDataItem)row;
if (row.FindControl("ttcNonStdPolTypeCdEdit") != null)
{
DropDownList ddl = (DropDownList)row.FindControl("ddlNonStdTypeCd");
ddl.ID += row.RowIndex;
ddl.SelectedIndex = 2;
NCCI.PDC.Web.Controls.ucToolTip ttcNonStdPolTypeCdEdit = (NCCI.PDC.Web.Controls.ucToolTip)row.FindControl("ttcNonStdPolTypeCdEdit");
ttcNonStdPolTypeCdEdit.getEditToolTip("non_std_pol_type_cd", ddl.ID);
}
}
}

Lost Focus Events for a Control Within GridView

I have multiple textboxes and dropdown lists within my GridView. For one particular textbox I need trigger a server event which gets data from the database and fills it in other columns of the Grid. Is there a simple way to do it or a slightly complicated way as detailed here
I have no problems implementing the above method or thinking of a work around but then thought that there is Cell Lost Focus in a grid control surprises me a little. Am I missing something ? Any help on this would appreciated.
You can set AutoPostBack to true and handle it's TextChanged event.
<asp:GridView ID="GridView1" runat="server" EmptyDataText="It's Empty.">
<Columns>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:TextBox ID="txtName"
runat="server"
Text='<%#Eval("Name") %>'
AutoPostBack="true"
OnTextChanged="NameChanged" >
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</GridView>
in codebehind:
protected void NameChanged(Object sender, EventArgs e)
{
var txtName = (TextBox) sender;
var row = (GridViewRow) txtName.NamingContainer;
// you could find other controls in this GridViewRow via
// row.FindControl("ControlID") in case of a TemplateField or
// row.Cells[0].Text (0 = index of column) in case of a BoundField
}

How to programmatically reach any AspxControl inside an AspXGridView's EditItemTemplate

Its very simple and i feel myself as an idiot :(
I newly started to using DevX Controls. Its documentation and sample projects are SUCKS!
My problem is:
I have an ASPxGridView on my aspx page:
<dx:ASPxGridView ID="dxdgMyGrid" runat="server" AutoGenerateColumns="False" OnStartRowEditing="DxGridStartRowEditing">
<SettingsEditing Mode="PopupEditForm" PopupEditFormHeight="200px" PopupEditFormWidth="500px"
EditFormColumnCount="2" PopupEditFormHorizontalAlign="Center" PopupEditFormVerticalAlign="Middle"
PopupEditFormModal="true" />
<Columns>
<dx:GridViewDataTextColumn FieldName="MyField1" VisibleIndex="1">
<EditFormSettings VisibleIndex="0" />
<EditItemTemplate>
<dx:ASPxDateEdit ID="dxdateMyField1" runat="server">
</dx:ASPxDateEdit>
</EditItemTemplate>
</dx:GridViewDataTextColumn>
<dx:GridViewDataColumn FieldName="MyField2" VisibleIndex="4">
<EditFormSettings VisibleIndex="1" />
<EditItemTemplate>
<dx:ASPxComboBox ID="dxcomboMyField2" runat="server">
</dx:ASPxComboBox>
</EditItemTemplate>
</dx:GridViewDataColumn>
</Columns>
How can i reach dxdateMyField1 or dxcomboMyfield2 on ASPX.CS file? I want to write:
dxcomboMyField2.DataSource = GetMyData2List();
dxcomboMyField2.SelectedItemIndex = 0;
... etc.
Thanks a lot.
You cannot access the EditItemTemplate Control Directly. You can access them at the HtmlRowCreated event as:
if (e.RowType != GridViewRowType.InlineEdit) return;
ASPxTextBox txtBox = ASPxGridView1.FindEditRowCellTemplateControl(ASPxGridView1.Columns["Name"]
as GridViewDataColumn, "ASPxTextBox1") as ASPxTextBox;
Check the documentation on Accessing Controls Contained within Templates
It is possible to cast the ASPxLabel.NamingContainer property to GridViewEditItemTemplateContainer and get a column value via the GridViewEditItemTemplateContainer.Text property.
But I like the technique of using the Init/Load event handler.When the grid switches to edit mode, the ASPxLabel.Load event is raised. Check this article The general technique of using the Init/Load event handler for implementation help.
[ASPx]
<dxe:ASPxTextBox ID="txtName" runat="server" Width="170px" OnInit="txtName_Init">
</dxe:ASPxTextBox>
[C#]
ASPxTextBox txtName;
protected void txtName_Init(object sender, EventArgs e)
{
txtName = (ASPxTextBox)sender;
GridViewEditFormTemplateContainer container = txtName.NamingContainer as GridViewEditFormTemplateContainer;
// You can remove the if statement, and try to insert a new record. You'll catch an exception, because the DataBinder returns null reference
if (!container.Grid.IsNewRowEditing)
txtName.Text = DataBinder.Eval(container.DataItem, "CategoryName").ToString();
}
Update Event:
protected void grid_RowUpdating(object sender, DevExpress.Web.Data.ASPxDataUpdatingEventArgs e)
{
e.NewValues["CategoryName"] = txtName.Text;
}
There is already an question - ASPxGridView - How to find a control inside the EditItemTemplate on DevExpress fourm .
You can use combo box init/load event handler for setting combo datasource. If that doesn't work for you, use FindEditRowCellTemplateControl (use link in comments for further explanation).

how do i get access to the label inside gridview/repeater

as you can see in my code... i have a label inside ItemTemplate and what i want is when i click on that particular control i would like to access to the label so that i can update the status...
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1" OnItemCreated="Repeater1_ItemCreated" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
Book:
<asp:Label ID="lblStatus" runat="server"></asp:Label>
<Mycontrol:Content1 ID="EmpControl" runat="server" OnMyControlClick="EmpControl_clicking" />
<br />
</ItemTemplate>
</asp:Repeater>
protected void EmpControl_clicking(object sender, EmployeeEventArgs e)
{
// how do i get access to the lblStatus???
}
You will need to use the FindControl method to access controls within templates:
protected void EmpControl_clicking(object sender, EmployeeEventArgs e)
{
MyControl myControl = (MyControl)sender;
Label c = (Label)myControl.Parent.FindControl("lblStatus");
}

Resources