Showing posts with label collapsiblepanel. Show all posts
Showing posts with label collapsiblepanel. Show all posts

Wednesday, March 28, 2012

Extender for two controls (Toggle-able Collapsible Panels)

I'm looking to build my first extender and the one I've chosen is a variation on the CollapsiblePanel so I've started with that control as my base. I've removed the ExpandControlID property and forced the CollapseControlID to always be a toggle. I've also added a property, CollapsePanelID, which is the ID of a second panel. At startup, the TargetControlID is expanded, the CollapsePanelID is collapsed and the CollapseControlID is used to toggle the two of them together.

I'm having trouble setting up the animation for the second panel. For the first, I see the line:
_animation.set_target( this );
I can't figure out how to call a similar function for the CollapsePanelID. I thought maybe there was a Sys.UI.Panel object I could create and configure for the second panel but I don't see one. The idea is that I would set up a second animation for the second panel, then in the _doOpen and _doClose functions, I'd play it along with the existing one.

This is for my own edification, not for any specific problem. I've already been able to do this functionally with two CollapsiblePanels. Just picked this as my project for learning extenders. Even as I write this, I'm thinking there might be a better way to do this but it would still involve the ability to create a Sys.UI control that maps to an asp:panel object.

Thanks,
Kyle

Hi Kyle,

Check out the JavaScript inFAQ item #13. It does essentially what you want - given an ID"Link1" it creates a newSys.UI.Control wrapper for it. This is what you need to pass intoset_target.

It's also worth mentioning that we've got a similar control in the works for the next release of the Toolkit. You check it out in the Prototypes project on CodePlex if you're interested.

Thanks,
Ted

Thanks, Ted. That FAQ item does look like what I want. I'll check it out.

Downloaded the source from CodePlex and had trouble opening the Prototypes project ("The project type is not supported by this installation"). I'll get it worked out but thought I'd raise the issue.

Thanks again,
Kyle


Never mind about the error. Read the instructions, installed the web app update and all is well.

Extender control nested in 2 DataControls

Hello all!

I have problem when using The CollapsiblePanel Extender control nested in 2 dataControls.

My Code like this

1<asp:DataList id="1" DataSourceID="sds1" runat="server">2 <ItemTemplate>3 <asp:Panel id="pl1" runat="server">4 <asp:Label id="lbl1" runat="server" text="<%# Bind("NewsTitle")%>"/>5 </asp:Panel>6 <asp:LinkButton runat="server" id="lb1"/>7 <asp:Repeater id="gv1" runat="server" DataSourceID="sds2">8 <ItemTemplate>9 <asp:Label id="lbl1" runat="server" text="<%# DataBinder.Eval(Container.DataItem,"NewsTitle")%>"/>1011<atlasToolkit:CollapsiblePanelExtender ID="cpe" runat="Server">12 <atlasToolkit:CollapsiblePanelProperties13 TargetControlID="pl1"14 CollapsedSize="0"15 ExpandedSize="300"16 Collapsed="True"17 ExpandControlID="lb1"18 CollapseControlID="lb1"19 ScrollContents="True"20 TextLabelID="Label1"21 CollapsedText="Show Details..."22 ExpandedText="Hide Details"23 ImageControlID="Image1"24 ExpandDirection="Height"/>25</atlasToolkit:CollapsiblePanelExtender>262728 </ItemTemplate>29 </asp:Repeater>30 </ItemTemplate>31</asp:DataList>

Then when view this page in browser, it throw the message "Can't find Control 'pl1' for the extender 'cpe'"

How can i fix this error? Thank all!

If you move the CollapsiblePanel declaration up a level so that it sits right next to the label/panel it touches, this scenario seems to work fine for me. Have you tried that?

HiDavid!

Thank for your reply! But, i dont want move it up a level, it must be this current DataControl.

Eample, in a news site, i use datalist for display a list of new catalogue, in each news catalogue, i display some news.

My extenderControl is not Collapsible Panel, it my owner, when you click in a news Title (This News Title is in DataControl level 2 -- so DataControl level 2 have more than 1 link like that) , an Panel near this DataControl level2 and in DataControl level 1 will display some text from server (This text get by My Extender control).

So, do you know why i cant not move it up a level?

I have try Reflector and saw this error message in OnPreRender (At Microsoft.Web.UI.ExtenderBase...<T>). And this Code only support for Control in this.Page or this.NamingContainer,...

I think Atlas not good in processing it, for the best, i think this code (or another code like this ^_^) is require to find All Control that name "ID"

Control myctl =this;Control control1;while (myctl !=null){ control1 = myctl.FindControl("ID");if (control1 ==null) myctl = myctl.Parent;else myctl =null;}

Do you think so?

Thank!


oh! Im so sorry! My code:


1Control myctl =this;23Control control1;45while (myctl !=null)67{89 control1 = myctl.FindControl("ID");10if (control1 ==null) control1 = myctl.NamingContainer.FindControl("ID");11if (control1 ==null) myctl = myctl.Parent;1213else myctl =null;1415}16

Okay, there's a way to do this, but it's subject to change in the future, so it's probably best not to rely on it. But what you can do to help resolve controls that couldn't otherwise be found is to add a OnResolveTargetControlID property to your extender and then write a simple method that does the resolution for you. The OnResolveTargetControlID method is called when the extender fails to resolve the TargetControlID using its usual steps (current naming context, parent naming context, page naming context). This applies only for TargetControlID, but when it works, it's nice. :) Here's a complete sample to demonstrate the concept. Note that I've got the same basic structure you have with the extender nested deeper than the control it's targetting. Hope this helps!

<%@. Page Language="C#" %><%@. Register Assembly="AtlasControlToolkit" Namespace="AtlasControlToolkit" TagPrefix="atlastoolkit" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><script runat="server"> protected override void OnLoad(EventArgs e) { base.OnLoad(e); xds1.DataFile = HttpContext.Current.Server.MapPath("~/App_Data/CarsService.xml"); } protected void ResolveTargetControlID(object sender, Microsoft.AtlasControlExtender.ResolveControlEventArgs e) { if ("p1" == e.ControlID) { e.Control = ((Control)sender).NamingContainer.NamingContainer.NamingContainer.FindControl(e.ControlID); } }</script><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Untitled Page</title></head><body> <form id="form1" runat="server"> <div> <atlas:ScriptManager ID="sm1" runat="server"> </atlas:ScriptManager> <asp:XmlDataSource ID="xds1" runat="server"></asp:XmlDataSource> <asp:DataList ID="dl1" runat="server" DataSourceID="xds1"> <ItemTemplate> <asp:Panel ID="p1" runat="server" BackColor="Lime"> Hello </asp:Panel> <asp:Repeater ID="r1" runat="server" DataSourceID="xds1"> <ItemTemplate> Hi <atlastoolkit:DropShadowExtender ID="dse" runat="server" OnResolveTargetControlID="ResolveTargetControlID"> <atlastoolkit:DropShadowProperties TargetControlID="p1" Width="2" /> </atlastoolkit:DropShadowExtender> </ItemTemplate> </asp:Repeater> </ItemTemplate> </asp:DataList> </div> </form></body></html>

e.Control = ((Control)sender).NamingContainer.NamingContainer.NamingContainer.FindControl(e.ControlID);

^_^
So many "NamingContainer" --> so fun.
Thank you first! I will try your help!

Hello again! i've try your help and get the best! thanks you very much, with other control, not the target, there is no problem!

But i want to know: Is there an other way to do this? Some time, we dont know how many 'NamingContainer' needed!


You could build a more flexible implementation that kept searching each naming container up the chain until it reached the top (null) or found the control. But the basic idea's the same as what I showed: find the control near where you expect it to be. Glad this worked for you!

Saturday, March 24, 2012

Events in Collapsiblepanel control

I'm using the Collapsiblepanel control for an article navigation system.

Here is the header element:

<asp:Panel ID="HeaderPanel1" EnableViewState="true" runat="server" Style="cursor: pointer;">
<li>
<asp:LinkButton ID="LinkButton1"
runat="server"
OnClick="LinkButton1_Click"
OnCommand="LinkButton1_Command">
HEADER LINK
</asp:LinkButton>
</li>
</asp:Panel>

Everything works fine in terms of panel collapsing and expanding, but I can't trigger events. This makes a kind of sense because the panel is probably already wired up with the toolkit code. BUT I need to be able to track if a panel is open or closed, so that I can recreate it later (When a user visits a main category page, expands a subcategory, and clicks an article in it, I need the panel in the same state it was in when we load up the page to view the article-perfect application for the collapsiblepanel, but no mechanism to persist state across PAGES).

The events I'm calling work just fine for any button controls outside of the collapsiblepanel. The code is fine; it's just no being called.

How can I add my own events within the header panel of the collapsiblepanel control? Do I need to create a collapsible panel from scratch in c# and then add events that way?

Hi,

If you plan to disable the extender from preventing an inner element to do postback, please set SuppressPostBack="false" on the CollapsiblePanelExtender. Otherwise, a postback will be intercepted.

Hope this helps.


Ray,

Is there a way I can collapse or expand the Collapsiblepanel through the code behind. And how can one read the current status of the panel in a program.

Kat


Hi Tedreagan,

My understanding of your issue is that LinkButton1_Click event is not catched by the server side. If I have misunderstood , please feel free to let me know.

Based on your description , I think your should check the CollapsiblePanelExtender's SuppressPostBack. It should be setted to "false" if you want send a postback when LinkButton1's click event is fired. Just like this:

<ajaxToolkit:CollapsiblePanelExtender ID="cpeDemo" runat="Server" TargetControlID="Panel1"
ExpandControlID="Panel2" CollapseControlID="Panel2" Collapsed="False" TextLabelID="Label1"
ImageControlID="Image1" ExpandedText="(Hide Details...)" CollapsedText="(Show Details...)"
ExpandedImage="../pic/collapse_blue.jpg" CollapsedImage="../pic/expand_blue.jpg"
SuppressPostBack="false" />

I have another sample which shows how to do some update work on the client side whenSuppressPostBack property is setted to "true"; May be you can benefit from it.

<%@. Page Language="C#" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><script runat="server"></script><html xmlns="http://www.w3.org/1999/xhtml"><head id="Head1" runat="server"> <title>ClickEvent</title> <style type="text/css"> .collapsePanel { background-color:white; overflow:hidden; } .collapsePanelHeader{ width:100%; height:30px; background-image: url(../pic/bg-menu-main.png); background-repeat:repeat-x; color:#FFF; font-weight:bold; } </style></head><body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <asp:TextBox ID="TextBox1" runat="server" Width="300"></asp:TextBox> <asp:Panel ID="Panel2" runat="server" CssClass="collapsePanelHeader" Height="30px"> <div style="padding: 5px; cursor: pointer; vertical-align: middle;" onclick="getCollapsibleState()"> <div style="float: left;"> What is ASP.NET AJAX?</div> <div style="float: left; margin-left: 20px;"> <asp:Label ID="Label1" runat="server">(Show Details...)</asp:Label> </div> <div style="float: right; vertical-align: middle;"> <asp:ImageButton ID="Image1" runat="server" ImageUrl="../pic/expand_blue.jpg" AlternateText="(Show Details...)" /> </div> </div> </asp:Panel> <asp:Panel ID="Panel1" runat="server" CssClass="collapsePanel" Height="0"> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate><%=DateTime.Now.ToString()%> <div style="display: none"> <asp:Button ID="Button1" runat="server" Text="Button" /> </div> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" /> </Triggers> </asp:UpdatePanel> </asp:Panel> <ajaxToolkit:CollapsiblePanelExtender ID="cpeDemo" runat="Server" TargetControlID="Panel1" ExpandControlID="Panel2" CollapseControlID="Panel2" Collapsed="False" TextLabelID="Label1" ImageControlID="Image1" ExpandedText="(Hide Details...)" CollapsedText="(Show Details...)" ExpandedImage="../pic/collapse_blue.jpg" CollapsedImage="../pic/expand_blue.jpg" SuppressPostBack="true" /> <script type="text/javascript" language="javascript"> var objExtender; // this will run automatically when the page has finished loading function pageLoad(sender, args) { objExtender = $find("<%=cpeDemo.ClientID%>"); objExtender.add_expandComplete(getCollapsibleState); objExtender.add_collapseComplete(getCollapsibleState); } function getCollapsibleState() { if(objExtender.get_Collapsed()) { $get("<%=TextBox1.ClientID%>").value="Now it is getting collapsed!"; } else { $get("<%=TextBox1.ClientID%>").value="Now it is getting expanded!"; //force the UpdatePanel to update $get("<%=Button1.ClientID%>").click(); } } </script> </form></body></html>

I hope this help.

Best regards,

Jonathan


Kat,

I've looked through the method that CollapsiblePanelExtender exposes, and it seems that it doesn't support this behavior on server side directly. You may use javascript to expand it. You also can get its state asJonathan 's sample shows.

To expand it, please use this script and register it as start up client script:

objExtender = $find("<%=cpeDemo.ClientID%>").expandPanel();
  


Thanks very much. This was the right solution for me.

Jonathan, your code sample was remarkably helpful. Thanks.

Raymond Wen - MSFT:

Hi,

If you plan to disable the extender from preventing an inner element to do postback, please set SuppressPostBack="false" on the CollapsiblePanelExtender. Otherwise, a postback will be intercepted.

Hope this helps.

Wednesday, March 21, 2012

Event handlers for behaviors using the extenders

Hi

Is there a way to set the handler for an event of a behaviour (i.e. expandedCompleted for CollapsiblePanel) using the extender and the extender properties?
In this case, the behavior has the event, but in the CollapsiblePanelProperties only the properties are available.

Thank you
Vlad

Unfortunately, this doesn't work because the events on the behavior are client side, and any event hookups done via the ASPX are server-side.

To hook up to those events, you'll need to it from Javascript, which is possible. I think you can set an ID property in your properties declaration and then access that object at runtime with "$object('idValue')". Once you have that, you can hook up to the event, but again, it's in script at runtime.


My understanding is that the extenders act as a helpers or wrappers for the atlas behaviors so that they can be used easier from Visual Studio(please correct me if i'm wrong). This means that the properties from the CollapsiblePanelProperties are passed to the CollapsiblePanelBehaviour.
Wouldn't it be possible then to pass the name of the event handler as a text property? Of course the event handler would have to be a javascript function, but the assignment could be done at design time, just like when the behaviors are used without the extenders, something like this:

<textBox id="myTextBox"> <behaviors> <clickBehavior click="onTextBoxClick" /> <keyPressBehavior keypress="onTextBoxKeyPress" /> </behaviors> </textBox>

Thank you,
Vlad

Yes you're right - I misread your question.

This is a good idea - thanks for bringing it up. One thing we're kind of sturggling with is how much to blur the client and server models. We've already crossed this line in a few places (very similar to what you propose actually) and I need to do more thinking about what the pattern is here. So you've "planted the seed", let me think more about this, what the semantics are, etc.

Shawn