To make certain form creation easier, we use a modified Formview control that is inside a User Control. This User Control is for a grid and a FormView, you can choose an item in the grid, and a FormView is presented in a modal for viewing/editing:
<I2CL:Grid runat="server" ID="Grid" OnSelecting="Selecting" ShowCreate="true" />
<I2:Modal ID="SFModal" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<I2:FormView runat="server" ID="FVSubForm" DefaultMode="Edit" DataSourceID="DSSubForm" />
<I2:ILDataSource ID="DSSubForm" runat="server" />
</ContentTemplate>
</I2:Modal>
In a page, the control looks like this:
<I2C:TabGrid ID="TG" runat="server" Property="ParentProperty">
<Columns>
<I2:Column Header="Column 1" DataSource="Column1" />
<I2:Column Header="Column 2" DataSource="Column2" />
</Columns>
<EditItemTemplate>
<I2Form:Dropdown ID="Col1" runat="server" SelectedValue='<%# Bind("Column1") %>' List="Column1Options" />
<I2Form:Textbox ID="Col2" runat="server" Text='<%# Bind("Column2") %>' />
</EditItemTemplate>
</I2C:TabGrid>
The problem is the EditItemTemplate we use. The only way I can figure out how to hook it up is to have an ITemplate in the TabGrid control and apply the reference in OnInit:
[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(FormView))]
public ITemplate EditItemTemplate { get; set; }
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
FVSubForm.EditItemTemplate = EditItemTemplate;
}
The problem with this is that because the reference is to an object in the user control, the EditItemTemplate reference that ties to the dictionary entries in FormView for changes are destroyed, so when you get the dictionary of changes sent to the datasource, they're empty on every postback.
The I2:ILDataSource used here is a custom implementation closest to ObjectDataSource. Instead of a generic object call, it directly calls a GetEntity() in the page (or user control in this case) and a UpdateEntity(obj Entity) to save. Since it's a very specific scenario, we can eliminate 90% of the code in ObjectDataSource.
What I want to be able to do is point the <EditItemTemplate> in the <I2C:TabGrid> directly to the <EditItemTemplate> of the <I2:FormView> inside. Is this possible, or anyone have suggestions of another route to go?
Note: I tried exposing the EditItemTemplate on FVSubForm as a proxy property, but this didn't work because the property is set on the user control before the child control is created, so FVSubForm is null. If this can be worked around, I'm certainly all ears.
One thing you need to do is mark your ITemplate property as supporting two-way databinding:
[TemplateContainer(typeof(FormView), System.ComponentModel.BindingDirection.TwoWay)]
Without this, ASP.NET will not generate the proper code for the page that allows Bind() expressions to work.
I'm not sure if that's all you need, but that's something to try.
David
Related
I have a some controls inside an EditItemTemplate within a RadListView control:
<telerik:RadComboBox ID="cbCategoryTypeTueET" runat="server" Skin="Office2010Black"
SelectedValue='<%# DataBinder.Eval(Container.DataItem, "CategoryTypeID") %>'
TabIndex="1" Width="100%" EmptyMessage="--Select Category Type--" DataSourceID="edsCatTypeTueET"
DataTextField="CategoryName" DataValueField="CategoryTypeID" AutoPostBack="True"
OnSelectedIndexChanged="cbCategoryTypeTueET_SelectedIndexChanged" AccessKey="t" AppendDataBoundItems="True">
</telerik:RadComboBox>
<asp:EntityDataSource ID="edsCatTypeTueET" runat="server" ConnectionString=""
DefaultContainerName="ATITimeEntry" EnableFlattening="False" EntitySetName="TimeTrackingCategoryTypes"
Select="it.[CategoryTypeID], it.[CategoryName]"
Where="it.deletedFlag = false AND it.activeFlag = true" >
</asp:EntityDataSource>
The Entity datasource does have a connection string - I am using a new code generation template - so this is not an issue.
My problem is I want the combobox to bind on edit. But if activeFlag is false or deletedFlag is true (or both) the Radlistview will not go into edit mode. Is there an elegant way to do this with markup or some elegant query?
My understandig is, you want to forbid edit on some conditions.
You have to subscripe the ItemDataBound Event from the RadListView. There you can cast DataItem to your object and check the condition (Get Data being bound to ListView).
Then you can access your controls and manipulate them (like hide them)...
Conditionaly disable command button
I have a search form in an updatePanel which retrieves a list of users in a grid in the same UpdatePanel. The name of each user is a commandLink. I want to make the commandLinks as PostBackTriggers.
But when I do it I get an error at the pageLoad time that the controlId does not exist and its true because the grid of users does not render at the load time but through an ajax call.
Any ideas on how can I make the multiple command buttons in a grid retrieved through ajax call as post back triggers?
When adding the items to the grid, within the ItemDataBound event handler, you should register the postback for each specific control (the static identifiers in your HTML declarations are essentially placeholders - not all things repeated in the grid can actually have the same ID). You do this using the ScriptManager.RegisterAsyncPostBackControl method:
The RegisterAsyncPostBackControl method enables you to register Web
server controls as triggers so that they perform an asynchronous
postback instead of a synchronous postback. When the
ChildrenAsTriggers property of an UpdatePanel control is set to true
(which is the default), postback controls inside the UpdatePanel
control are automatically registered as asynchronous postback
controls.
As stated above, using ChildrenAsTriggers is a possibility, too, but this is commonly set to false for more stringent management.
I have found the solution. Here is the code on asp
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtFirstName" runat="server"></asp:TextBox>
<asp:Button ID="btnSearch" runat="server" OnClick="btnSearch_Click" Text="Search" />
<asp:GridView ID="gvSearchResult" runat="server" OnRowCommand="gvSearchResult_RowCommand"
OnRowDataBound="gvSearchResult_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:LinkButton ID="lnkbtnDetail" runat="server" CommandArgument='<%# Bind("CNIC") %>' CommandName="Detail">
<asp:Label ID="lblName" Text='<%# Bind("Employee_Name") %>' runat="server</asp:Label>
</asp:LinkButton>
</ItemTemplate>
<ItemStyle HorizontalAlign="Left" VerticalAlign="Middle"Height="25px"Width="30%" />
</asp:TemplateField>
</Columns>
</asp:GridView>
Ihad to place OnRowDataBound="gvSearchResult_RowDataBound" on gridView and that function looks like below. So I had to register the iterative control in Scriptmanager as PostBackControl in RowDataBound event of GridView.
protected void gvSearchResult_RowDataBound(object sender, GridViewRowEventArgs e)
{
try
{
if ((e.Row.RowType == DataControlRowType.DataRow))
{
LinkButton lnkbtnDetail = (LinkButton)e.Row.FindControl("lnkbtnDetail");
ScriptManager.GetCurrent(this).RegisterPostBackControl(lnkbtnDetail);
}
}
catch (Exception ex)
{
}
}
I am new to ASP.net thing, and i have some question regarding postback.
I have a Senario like this:
1) I have a grid on web with a panel inside.
2) I "Insert" the panel with a Web User Control by calling this
Control ctlControl;
ctlControl = LoadControl("~/UserControls/ChequeCreation.ascx");
pnlTransaction.Controls.Add(ctlControl);
3)The Web User Control providing two button. One is "update" and one is "reset".
Problem is like here:
What i wanted to achieve is when press the "update" button, it will update something back to my DB? But seem after i press the button "Update" or "Reset". The web user control is gone or missing. For my guest is because of the postback issues? Is that correct?
I tried if(!postback) still its doesn't work.
How am i going to overcome this? I already scratching my head about a day?
Thanks you so much.
Regards
LiangCk:
PS:Sorry for my english level, and please dont hesitate to voice out my error or mistake.
well you can convert any of your data columns to template column and then drag and drop your web user control to it
this will result in something like the following code check where "uc1:webUserControle1" is located in the code
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" DataSourceID="SqlDB">
<Columns>
<asp:TemplateField HeaderText="ID" SortExpression="ID">
<EditItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("ID") %>'></asp:Label>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("ID") %>'></asp:Label>
<uc1:webUserControle1 ID="WebUserControle1_1" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="name" HeaderText="name" SortExpression="name" />
</Columns>
</asp:GridView>
if you are using AJAX, try add updatepanel on your UCT design page
ASP.NET will not preserve a dynamically added user control between postbacks. This is why it is dissapearing. You will need to add the control each time the page is created. However you will need to add it when the control tree is being initialized and restore the original control ID if you want your events to fire. These links provide a full explanation https://web.archive.org/web/20210330142645/http://www.4guysfromrolla.com/articles/092904-1.aspx and http://avinashsing.sunkur.com/2011/02/24/dynamic-controls-viewstate-and-postback/
You have to Every Time Reload the user control on Page_Init or
Page_Load. Then you can get the Button Click Event and After tha User
Control will not lost.
private void LoadUserControl(){
string controlPath = LastLoadedControl;
if (!string.IsNullOrEmpty(controlPath)) {
PlaceHolder1.Controls.Clear();
UserControl uc = (UserControl)LoadControl(controlPath);
PlaceHolder1.Controls.Add(uc);
}
}
protected void Page_Load(object sender, EventArgs e) {
LoadUserControl();
}
I am trying to have a collapsible panel inside of a listview item. In the item template, I have a panel, and a collapsible panel extender. In order to set the attributes TargetControlID, CollapseControlID, etc., I need the ClientIDs that are generated after databinding for each of the listview items. Does anyone know how I can set those attributes client-side?
I've tried various things along the lines of the following:
<ItemTemplate>
<asp:Panel ID="ManagingPanel" runat="server">
</asp:Panel>
<asp:CollapsiblePanelExtender runat="server" TargetControlID='<%="ManagingPanel.ClientID" %>' />
</ItemTemplate>
SOLUTION - Turns out you do not need to use the ClientID. The Extender will recognize that its target is inside the same listview item.
<asp:CollapsiblePanelExtender runat="server" TargetControlID="ManagingPanel" />
I have create a custom user control that includes the CollapsiblePanelExtender and every other think that I like to show, a complex html struct, and then I have include this control in the repeater.
The repeater pass the data that I need to render my custom control, and then the custom control render its self in every line of the repeater, and all is working fine.
something like
<asp:Repeater ID="myRepeater" runat="server">
<ItemTemplate>
<uc1:MyCustonControl ID="lPro" runat="server" data="<%#PassData%>" />
</ItemTemplate>
</asp:Repeater>
Turns out you do not need to use the ClientID. The Extender will recognize that its target is inside the same listview item.
<asp:CollapsiblePanelExtender runat="server" TargetControlID="ManagingPanel" />
I have a a custom control declared as
[SupportsEventValidation, DefaultEvent("ActiveTabChanged")]
[ParseChildren(true)]
[PersistChildren(false)]
[ToolboxBitmap(typeof(System.Web.UI.WebControls.Panel))]
public class TabContainer : System.Web.UI.WebControls.PlaceHolder, INamingContainer, IPostBackDataHandler, IPostBackEventHandler
{
when I use this in my code markup, I use it as
<MDSL:TabContainer runat="server" ID="t1">
<ClientEvents>
<TabChange EventHandler="onTabChanged" />
<Load EventHandler="onTabLoaded" />
</ClientEvents>
<Tabs>
<MDSL:Tab ID="tablInvoice" runat="server" HeaderText="Invoice">
<ContentTemplate>
<MDSL:TextBox ID="TextBox1" runat="server" Text="in new tab"></MDSL:TextBox>
</ContentTemplate>
</MDSL:Tab>
<MDSL:Tab ID="tabTzhirdTab" runat="server" HeaderText="My new Shiny Header Text">
<ContentTemplate>
<MDSL:Label ID="lbldNew" runat="server" Text="Woohhoo!!" DataField="" DataFormatString=""
meta:resourcekey="lbldNewResource5"></MDSL:Label>
</ContentTemplate>
</MDSL:Tab>
</Tabs>
</MDSL:TabContainer>
Everything works fine as I would expect it to. However if I go to design view and do a "Tools -> Generate Local Resources" then pretty much nothing happens :( If I however mark this as
ParseChildren(false)
then the meta tags appears and everything happens as I would expect it to happen. Can anyone help me here?
Thanks!
Nik
Solved it myself. It was the way I was handling the override of CreateControlCollection() method. I needed some special handling of this method in the design view. Then I also needed to use the DesignerSerializationVisibility attribute correctly on a few public properties of the control.