rendering multiple Calendars bloats html, bogs down page - c#

note: I am using the Infragistics control because this is inherited legacy code, but I am not above rewritting with an ASP.NET control if that is a better solution.
I have a Repeater control that uses an Infragistics WebDateChooser to select a date for a record. Let's say each item in the Repeater represents a customer, and I am selecting an activation date or something of that nature. It could be any time past, present, or future.
When you render this control 20 times, it writes all of the heavy html for showing all of the dates (month names, weekdays, etc etc) 20 times and bloats the html dramatically. This causes the browser to really struggle with rendering the page in any reasonable amount of time, even for 20 records (paging implemented on the repeater just to prevent the browser from crashing on massive page). This is also true to a lesser (but still significant) degree with the standard ASP.NET calendar control.
What I'm looking for is a way to possibly make all 20 date choosers share the resources of 1 calendar so they don't each need to render their own strings and crap for displaying verbose dates.
EDIT:
I understand many users have not used Infragistics, but it's still just as true with the standard, built in ASP:Calendar control. Put one in a repeater and display n > 20 times. It bogs down the browser when rendering.
Also, just to clarify incase this matters to anyone's potential solution, this codebase is on .NET 2.0 and has to support IE6.

Another thing you might consider is to have one instance of the calendar on the page. When the user clicks a textbox that "activates" the calendar, you can use a client-side javascript framework like jquery to show the calendar and move it the correct expected position. Once the date is selected, store the selected date in the correct text box and hide the calendar again. You'll have to write some javascript but it beats downloading all the extra bloat!

If what you are looking for is a Datepiker that is called and displayed on each date field in a grid, calling a JavaScript calendar is the most efficient. Check out the JQuery ui calendar and just put the call on each field -- see: jqueryui.com/demos/.
HTML -- note the class is the same and ID different:
<input type="text" class="datepicker" id="d1" />
<input type="text" class="datepicker" id="d2" />
JQuery then selects the css class:
$(.datepicker.each(function() {
$(this).datepicker();
});
The older ASP.Net solution is for a control to be declared and dynamically instantiated on the server when the click even is fired. There are many example of this on lots of blogs. Or 20 of them can be created on page load and placed in a datagrid or something. But what if the datagrid has 100 entries? It cannot scale.
But there is a calendar in the AJAX control toolkit that is created once on a panel and then that panel is displayed where you tell it. It is one calendar, shown many times.
<asp:Panel ID="panelCal" runat="server">      
<asp:UpdatePanel ID="update" runat="server">           
<ContentTemplate>   
<asp:Calendar ID="theonlyCal"runat="server"/>           
</ContentTemplate>      
</asp:UpdatePanel>
</asp:Panel>
Now say there are 20 rows:
<asp:TextBox ID="twenty" runat="server" />
Now each text box needs a popup control extender.
<ajaxToolkit:PopupControlExtenderID="twentExtenders"runat="server"
TargetControlID="twenty"
PopupControlID="panelCal"
Position="Bottom" />
ASP.NET AJAX can use lots of bandwidth.

I haven't used the control you are so I can't say if this one will work for you but I highly recommend: http://www.dynarch.com/projects/calendar/ It's a javascript calendar so the user will only download the js includes once. After that the creation calls are just a few lines.
It's not immediately "drag-and-drop" compatible with ASP.Net. I recommend wrapping it in a user control.

While it doesn't unify into one instance of the control, could you use the CalendarExtender that comes with the AjaxControlToolkit. I just built a small example on my machine and it didn't bog the page down that much.

Well the example at Infragistics definitly shows that the control was built to be reused like this. They aren't using a Repeater of course but it all works the same in the end. I would look into how the UltraGridColumn is working with the WebDateChooser to display the dropdown.
Of course, this won't help with the more general problem. For that I would do as the others say and create one control and use javascript to display it where it is needed, when it is needed.
If you really don't want to write any javascript yourself you can take advantage of the toolkits. You could create an instance of whatever calendar (not the dropdown version) and use the AjaxControlToolkit's modalpopup, Infragistic's WebDialogWindow or something similar (perhaps with less dialogy more floaty) to display it.
In the end all the options have one thing in common. They create a single calendar outside of the repeater and display that instance of the calendar on demand.

Related

How to ensure viewstate is disabled on a large number of checkbox controls?

I have an ASP.NET web form that has several thousand checkbox controls (in a parent/child hierarchy). The page takes about 4 seconds to load. I'm trying to increase the performance so that the page only takes ~1-2 seconds to load. After doing some digging, it looks like the checkbox controls are generating a massive viewstate object (almost 1MB in the HTML file). If I use raw HTML checkboxes, the page renders very quickly (and I think it's due to the fact that the viewstate isn't being created). I tried going down the raw HTML chechbox route, but am having trouble calling ASP.NET methods from JS using dopostback. Anyway, my main goal is to eliminate the viewstate on the checkboxes. I've tried doing this by disabling viewstate on the checkbox controls as well as on the ASPX page. Regardless of what combo I use, the viewstate object is still being created (and as I said, it's massive). I've even tried to clear the viewstate object in the code behind at all the major events that fire. Still no luck at clearing out the viewstate. Any suggestions on what I can do to disable viewstate on the checkboxes to avoid the overhead of what looks like is causing a performance bottleneck?
One way to keep the page as it is, is to warp your check boxes, with a place holder and set EnableViewState="false" for this one.
<asp:PlaceHolder runat="server" EnableViewState="false">
<asp:CheckBox runat="server" ID="cbOne" />
</asp:PlaceHolder>
Other way is to place them all inside a custom control and set EnableViewState="false" for this control.

ClientIDMode="AutoID" in Asp.net

Hello Everyone I am a newbie in asp.net,
I have a checkbox inside a repeater which is inside an update panel,the page flickers whenever I click the checkbox, finally found that adding the ClientIDMode="AutoID" controls the flicker and everything works fine.
I am wondering about ClientIDMode what this has to do with the flicker,
went through msdn and found it generate the value of the ClientID property.
First distict the asp.net controls, from the final rendered html controls.
When you make asp.net controls you give them an ID, with this id you can address them and make change on them on code behind and with programming in general.
For example with this code
<asp:CheckBox id="check1" Text="option a" runat="server" />
you can use the check1 to get their value, change the text, and many others.
Now, asp.net must render this check box on the html page. When you make any control on an html page you must set to him a unique ID and name, and heres come the automatic id assignment.
asp.net take care to avoid conficts between final rendered controls and make automatic ids base on the structure that you have use on asp.net side.
For example, if this control is inside a custom control, and this control is inside a master page, asp.net will add also this names on the final id, to avoid conflicts.
Conflicts can exist for example on a repeated control, where you render the same control many times, so there you need to change each rendered id.
Conflicts can exist when you use many times the same user control.
Conflicts can exist when you use the same id on different user controls on the same page.
All that and many others asp.net comes and solve with the automatic generated id on client side render.
Yes, it does have something to do with the flicker.
See this related question for another example of the fact that Repeaters don't handle client ids well, causing exactly this problem because they end up doing a full postback instead of a partial postback.
Setting ClientIDMode="AutoID" is the workaround and allows the Repeater to succeed in doing the partial postack it is supposed to be doing from within the UpdatePanel.
Because of this Repeater bug, without ClientIDMode="AutoID" you were experiencing a full postback and full page load. A full page load does cause a flicker compared to a partial page load.

Datagridview or something else?

I'm writing a winforms application which stores its data as plain text files and presents it to the user as a multi-column list. I'd like the user to be able to sort and filter the list, and also to re-order and hide/unhide columns.
I thought a DataGridView would be a good fit since it has a lot of that functionality built in, but I'm going to need some cell types (a date picker for instance) that are not available out of the box with a DataGridView. I know you can host controls inside a DGV and have read a Technet article on it, but it seems fairly complex and I'm newish to C#, Winforms, and OOP. A DGV is also not the prettiest control, and even though I know how to change its properties to make it look somewhat nicer, it never gets to where I really like it. Appearance isn't a dealbreaker if it's the way to go, but it's a "nice ot have."
So my question is: should I be struggling through getting the DGV to do what I want, even if it takes me longer and is more frustrating to do, or should I be rolling my own custom control(s)? I've created a couple of user controls in the past and am fairly comfortable with that.
Brian is right in the comment above. If you want customization, WPF is the way to go. However, coming from a WinForms background and starting fresh with WPF will be a steep learning curve.
Writing you own DataGridView-like control from scratch I don't view as a viable option. Reflect the code for the DataGridView and you will see why, there are thousands of lines of code for this component. If you mean that you will override the DataGridView class then, cool, that is a good idea. If it is cell based controls like the data picker you want you may be better overriding/sub-classing the DataGridViewCell instead...
You can customize the appearance of the DataGridView to make it look good out-of-the-Box, but don't underestimate the amount of time it will take to sub-class/inherit from DataGridViewCell to make something like a DataPicker, it won't be that enjoyable, but of course possible...
You can get the filtering you require, by just binding the grid to a DataSource like a DataTable and filtering that. This will automatically filter the displayed results.
I would think about using an existing library for this, as you will be reinventing the wheel to a large extent. Of course most controls are commercial and not free; but there must be some that are...
I hope this helps.
I have been using Infragistics for a few years now. Their WinForms products are very good, and in particular, their win grid control sounds like it would meet your needs. You can even use their grid columns in DataGridView if you don't want to use their grid (their grid takes a little bit of time to get used to). Their controls are somewhat expensive, but it's there if it suits your needs.
A good alternative for DataGridView is SourceGrid:
https://sourcegrid.codeplex.com/
I tried a test with a calendar form I use for our system:
Private Sub dgvTaskLog_CellContentClick(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvTaskLog.CellContentClick
Dim frm As New frmCalendar
frm.ShowDialog()
If IsDate(frm.outSelectedDate) Then
dgvTaskLog(e.ColumnIndex, e.RowIndex).Value = frm.outSelectedDate
End If
End Sub
When the user clicks on the cell the custom calendar form opens. You would most ikel ned to do some checks on what column to just display the calendar (or other "control") for that column. Not sure how this works for tabbing around cells, you may need another event to pull it off.
The custom form hosts the VB.Net calendar control and adds local business logic. If a valid date is returned it is stuffed into the cell. If the grid is bound you would need to update the datasource instead.
Any way - just another possible option.
Personally, I would stick with the DataGridView in WinForms. Instead of making a date-picker cell type, I would instead consider just launching a new Form with a date-picker on it to handle the actual time/date entry into the cells. This would give you the customization flexibility you need while not adding complexity to the DGV. The DGV can be left mostly or completely as-is with just out-of-the-box functionality, and then you can build your custom functionality around it as suggested with the date-picker on your own custom form, for example.
Good luck.
Extending the functionality of a DataGridView isn't easy but can be done as I've done it before Report Manager. You can also create custom field controls. Perhaps it might be easiest to create a template field with your gridview and use the ajax calendar extender.
<asp:GridView ID="myGridView" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="myTextBox" runat="server" />
<ajaxToolkit:CalendarExtender ID="calDate" runat="server" TargetControlID="myTextBox" Format="MM/dd/yyyy" SelectedDate='01/01/2016'></ajaxToolkit:CalendarExtender>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

ASP.NET web control only allow specific contents?

I am new to ASP .NET web controls, but not ASP .NET in general or C#.
I am wondering how I can limit the allowed content types to a specific class.
I have made a custom web control called TabPanel, and I want it to only be able to contain TabPages.
As an example, the following markup should be illegal, since it contains a checkbox.
<cc1:TabPanel ID="TabPanel1" runat="server">
<cc1:TabPage runat="server">
this is a simple test
</cc1:TabPage>
<cc1:TabPage runat="server">
this is another simple test
</cc1:TabPage>
<asp:CheckBox runat="server" />
</cc1:TabPanel>
In this case, I wouldn't want the checkbox to be there. How can I block this from happening?
I have not tried exactly what you are after but based on other things I have done I would try this:
Create a property in TabPannel that is a collection of TabPages (call it Tabs for demonstration purposes). This can be an array, a list, or a custom collection class, the key is to have typed to only accept TabPages as members.
Give the property the [PersistenceMode(PersistenceMode.InnerProperty)] atribute.
Override CreateChildControls to add the contents of the collection to the control.
If you do it this way then your mark up should end up looking something like this:
<cc1:TabPanel ID="TabPanel1" runat="server">
<Tabs>
<cc1:TabPage runat="server">this is a simple test</cc1:TabPage>
<cc1:TabPage runat="server">this is another simple test</cc1:TabPage>
</Tabs>
</cc1:TabPanel>
and it should not allow anything that is not a TabPage to be nested inside of the Tabs property.
http://msdn.microsoft.com/en-us/library/9txe1d4x(v=VS.90).aspx is a walk through demonstrating this technique in detail.
I figured it out.
Had to throw an exception under AddedControl procedure that I overrided from the WebControl if the type of the control being added was not of the type I wanted.
Now the designer shows a beautiful red error-message on the control itself, preventing me from doing such a foolish thing.
Awesome!
I'm going to take a guess here, but based on some quick googling I think you're looking for the ControlBuilder. The demo limits their control to an object called "mycell", but I don't see any reason why this couldn't be limited to your own objects, or build-in ASP.NET controls (i.e. Panels but not TextBoxes, etc.)
As a last resort, I'm sure you could hijack the rendering method and only render controls within the pre-determined class set, but this seems hack-ish at best.

Using Ajax method (how to do it)

Using an update panel in ASP.NET and with the help of a good tutorial on ListView from Matt Berseth I accomplished the image below.
alt text http://www.balexandre.com/temp/StackOverflow_HowToStartUsingAJAX.png
The behavior is, when I click the BOLD names, the rows below that name with numbers are collapsed.
Getting the DATA:
This is a SDK WebService that I cannot change, and with it I get the bold names in one call and for each bold name the list of the numerable rows, in this example I had to call 4 times the Web Service
1 call to provide me with all bold names and then 1 call per bold name to get the secondary list.
My employer told me to not do this, but only get the secondary row when a user clicks in the bold name ...
What should I do now? I'm kind'a lost here. :(
I know "what to do" but not "how to do"
I created a new row in the HTML to be replaced using jQuery
in the listView_ItemDataBound method I change the javascript to have that Row ID in order to be easier to use the javascript function
But, how do I show a "loading" image in that particular Row and load the secondary list?
(I already have a big one that is used to show a wait message when retrieving the bold names list)
alt text http://www.balexandre.com/temp/SuperOffice_forum_loadingIndicator.png
Do I need to create a middle WebService of my own to request this data right?
BIG problem is that I need to check "On Submit" those checkboxes in the secondary rows as well :(
I'm completely lost here, can anyone show me the light please?
ASP.NET Ajax can can use UpdateProgress the to display an image or anything.
<asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="updPanel1" DisplayAfter="0">
<ProgressTemplate>
<img alt="Please Wait" src="Images/processing.gif" />
</ProgressTemplate>
</asp:UpdateProgress>
You can use javascript to move it to any area on a page by setting the position to absolute.
The best way to do this solution is to program the who page using post backs. Then put an Ajax UpdatePanel on the page.
The web services you can call on the click event on each of the row to populate the data. Put the data in a panel that is hidden. Use Jquery and a start up script to display it if want it to "slide" down.
The best advice I can give is don't worry yet about having a real slick UI. Get the page working, and get the data from the web service. Then after you have that done, work on getting the UI to look better.
This is like playing music, you can't write all the parts of a song at once. You start with a theme then you create the melody, the second and 3rd parts etc. . . .

Categories

Resources