For most ASP.NET developers, the DataGrid control is a basic tool, just like the PIZZA producer's roll. The DataGrid control in the ASP.NET 1.x is a powerful and divertive tool. But you can make it more powerful by adding a little script code on the client. So far, I have not combined JavaScript with the DataGrid control. Recently, I saw a magical article written by Dave Massy for its "DHTML Dude" column on MSDN® Online. He reborn it in innovative ways. In addition, DAVE also demonstrates how to index and perform the drag of the contents of a table. He also demonstrates the use of DHTML behavior in a
element. I realized that the DataGrid control is an ordinary
element when generating HTML and sent to the browser. Therefore, I confirm that it may contain many attribute models, but their framework is a typical HTML table. This makes me realize that I can build a DataGrid control with column drag and client sort. The magazine column of the month was built into my experiment. You can download the source code to confirm that I am not lie to you. DHTML Behavior Quick Browsing DHTML Behavior has a key role in the implementation of a rich DataGrid control. You will see it, I can't use its behavior as a Dave defined. To make these behaviors valid in the context of an ASP.NET control, some changes are required. Although JavaScript skills do not require JavaScript skills when using this modified component, it is necessary to quickly review the DHTML behavior technology, mainly to better understand the mechanism of work with the server-side code. A DHTML behavior is a script component that binds the CSS style to an HTML tag. If your code is executed on an old browser that does not support CSS or does not identify behavioral style, unknown models will be ignored. For more deeper understanding DHTML, see "Scripting Evolves to a more Powerful Technology: HTML Behaviors in Depth". (Script enhances to a more powerful technology: in-depth HTML behavior) A DHTML behavior is a set of JavaScript functions plus a collection of public members that use a particular symptory definition. Typically, public members include attributes and events; sometimes also a method. Behavior works on the top level of the existing HTML element to allow you to rewrite and extend the behavior of the HTML element. In order to achieve this, a behavior can attach its code to one or more DHTML standard events. For example, a behavior can provide processing that dragged in the onMouseDown and onMouseUp events. What is even more, all special DHTML behavior can handle the onContentReady event, which is triggered after the HTML subscar (in the HTML of a particular element) is fully resolved. The onContentReady event is a good time to initialize a behavior. The core of behavior is a COM object that exposes some interfaces to Microsoft® Internet Explorer (version 5.0, and higher), but you can write them as a C binary component or HTML component (HTC) text file. The HTC file can be deployed to the server with files (HTML, ASP, and ASP.NET), and the client does not need any installation.
The following code shows how to add columns to a
tag:
Note: DragDrop.htc file must be used with files with it Under the same directory to the server. Dragable DataGrid After reading the Dave Massy column, I downloaded the DragDrop.htc example component and tried to bundle it into a DataGrid component in an example page, as follows: THEGRID.Style ["behavior"] = "URL (DragDrop" .htc) "; Strangely, this code does not work. I am sure that a DataGrid in the client is just a form, I decided to compare the source code in the Dave's example table and the HTML source code of the ASP.NET DataGrid, I noticed in ASP.NET 1.x, The table generated by the DataGrid does not contain the AD and TBODY elements. But the element is the basis for example behavior. To implement column drag and drop behavior, thead and tbody elements are not required, but they will be easy to position heads and gates. You either rewrite a behavior without THEAD and TBODY or write a custom DataGrid control that can be output with THEAD and TBODY tags. For an ASP.NET developer like me, I believe that writing a custom control is easier than editing a behavior. I think I need at least an efficient debugger to simply track my code. So I launched a new Visual Studio® .NET program and established an ASP.NET example app and a web control library project. The new DataGrid class has the following prototype: [ToolboxData ("<{0}: DataGrid Runat = /" Server / "/>")] public class datagrid: system.web.ui.webcontrols.dataGrid
{
Public DataGrid (): Base ()
{
EnableColumnDrag = true;
Dragcolor = color.empty;
Hitcolor = color.empty;
}
...
} Constructor initialize three common custom properties: EnableColumndrag, DragColor, and Hitcolor. EnableColumnDrag is a Boolean property that means that it is allowed to drag and drop. When this property is false, the custom DataGrid control does not add drag and drop behavior. Other two attributes define the foreground color of the background color and target columns of the top. Note that these two color properties do not affect the logic of the DataGrid server-side control. They are only simple server-side properties to output HTML displayed on the client. This two attributes are generated as the label custom attribute generated by the DataGrid. DataGrid's tag code can be generated in the render method of the control. See Figure 1, two behavior properties are added to the DataGrid's properties collection, and generates as the following small code:
render method generates a
element with the THEAD and TBODY tags. You can only implement this function in a way, that is, capture the default HTML tag and parsed. You can use the following code to capture HTML code generated for a given control: StringWriter Writer = new stringWriter (); htmlTextwriter Buffer = new htmlTextWriter;
Base.render (buffer);
String GridMarkup = Writer.toTString (); You can build a new HTMLTextWrite object and bundled it into the WRITE object used to write. At this time, the write operation is represented by a memory block, which is also a StringWriter object. Any content of any Writer object sent to HTML is actually aggregated in the write string Writer. The render method of the base class generates the standard tag of the DataGrid, and you can capture the standard tag and convert it into a string using the StringWriter's toString. This method is simple and effective. At this point, the parsing string is too easy to add THEAD and TBODY. The Thead tag is usually the first line of the table, which usually contains a header in each column. TBody tag table content area:
Column 1 TD>
Column 2 TD> TR>
THEAD>
Some TD>
Data TD> TR>
More TD>
INFO TD> TR>
tbody>
table> Finally, you write the modified tag to the response stream. Then you can prepare for testing. Compile the source code into an assembly (ASSEMBLY) and register the new control with Visual Studio.net. Next, the control to the Add Example page. This step will insert the following code to the .aspx file: <% @ register tagprefix = "msdn" namespace = "expoWare.Controls"
AskMBLY = "MyCTL"%> Use custom DataGrid as the DataGrid using the base class. You need to change its namespace prefix. If you need it, you also add some custom properties, such as: ...
msdn: DataGrid> Figure 2 Drag Rie Figure 2 shows the results of the example page. If you are dragging the operation, a translucent panel representing the column will move with the mouse. To improve the user experience, any column under the mouse will change the background color of its head to reflect it is a potential goal. When you release the mouse, the transparent column will interpret the front (left) of the following (left). Finally, the table will reflect to reflect the new order of the column. All of this will use the client DHTML object mode and do not need to interact with the server. Mouse events and table reconstruction will be managed by DHTML behavior. Enhanced drag and drop behavior Figure 3 provides several event-based behavioral code advanced views. The onContentReady event represents the entry point. The event's processing routine initializes the status of the component and accesses the public attributes defined in the additional element. In particular, DragDrop.htc behavior establishes a unit coordinate array to detect source columns in drag and drop. The width of each unit uses DHTML's ClientWidth property to track, which is a modification for my source code in the Dave column. The ClientWidth property retrieves the DHTML object contains filled, but does not contain narrative, borders, and scroll bars. Using this property is the key because it allows you to use columns without using the width in the HTML source code. Since I want to apply behavior to a custom DataGrid control, ITOGENERATECOLUMNS mode to support ASP.NET DATAGRIDS is an inevitable use of ClientWidth. Dragdrop.htc files in download this month also include other small modifications, most of which are based on personal hobbies. For example, in the drag and drop, the feedback control is displayed. Custom DATAGRID Control When the EnableColumnDrag property setting will set a behavior pattern. This property saves its value in the view state. If the attribute is set to true, the behavior attribute will be added to the DataGrid's style object. Note: Multiple behavior can be bundled to the same element. EnableColumNDRAG attributes is highly coupled. If the DataGrid does not display a header, the column drag will be automatically disabled. Figure 4 shows how to get and set an accessory properties of the two properties. Note that you need to be able to write the attachment properties of the ShowHeader property to ensure that the EnableColumNDRAG attribute is also set to false when the ShowHeader property is false. So far, you can discharge the drag and drop when you display DataGrid. However, the original order will be restored immediately when the page or DataGrid is refreshed. So how do you keep new order? Sustained new column sequestrations must be passed to the server side when the client's new column order information must be transferred to the server. There is nothing special in ASP.NET programming mode. Pass the new column order to the server side as the content passed in a text box or drop-down list is the server side. Transfer column sequence to the server side and force DataGrid to generate columns in the new order. Let us first handle information exchange. When using HTML and HTTP, there is only one way to pass client information to the server side, that is, the hidden field. DataGrid Control Add a hidden field to page; DHTML behavior draws the new column order and will write it to the field. When the page is refreshed, DataGrid retrieves new sequences from the hidden field and generates them. You can take any name for this field (as long as the name is unique). Of course, it also needs to be responsible for retrieving this value. The order of the new column will be represented in a comma-separated string, and the string also contains information about the list. Note that this method is arbitrary, but in any case, you must return a string.
You can use Page.Request to retrieve the value of the client: string desiredorder = page.request [hiddenfieldname] .tostring (); This scheme resolves this problem to allow you to have consistent column drag and drop characteristics. Despite effective, it is not the best method in ASP.NET. Have you used the iPostBackDataHandler interface? This interface will be very effective when you have a control from the client input data. Figure 5 shows the implementation of the iPostBackDataHandler interface in custom DataGrid control. Basically, the interface method allows you to automatically bundle one or more attributes that hide the fields to control. You don't need to call Page.Request yourself and you don't need to worry about hidden fields. ASP.NET will be processed. This interface lists two methods, which use only one method: loadPostData, which passes a key and the transmitted value collection. This button is only the control ID, and the collection is a subset of page.Request. This collection contains all input fields in all matching pages. In one case, the collection does not match the page.Request, that is, when the page is configured to control. The LoadPostData method is after the OnNit event and is requested before the OnLoad event. ASP.NET calls the LoadPostData method for implementing interface control only when the Control ID matches a input field. For such reasons, you must specify the same ID as the plaid. DataGrid works only on the passed data and does not need to send server-side information to the client. Based on this, you can build an empty string hidden field, as follows: page.registerhiddenfield (ID, "); loadPostData method refreshes a value named ColumnOrder's new attribute. This attribute will be used to determine the order in the form. Please note that if you have a column drag in two consecutive refreshes, the columnorder property will be empty. To keep the previously set column order, you must maintain the value of columnorder - for example: in view mode. In addition, during the refresh process, you should rewrite this property without null values. The second method of the iPostBackDataHandler interface allows you to trigger server-side events when refreshing values affects. Getting a string of a column order in the client is just half of the task. Now you have to tell DataGird to show columns in the correct order. DataGrid interpretator You have also paid attention to a secret of DataGrid? A friend said that I am a "DataGrid reader", he said that it is my ability to force hateful to control the way I hope. However, I have to admit that the fixed order for enforcing a DataGrid change column is quite difficult, even for those who have quite experience. I used a few hours to try to rearrange the column set of DataGrid from the OnLoad event. In this case, I realized that the collection is empty when the column is automatically generated. In addition, when controlling its HTML, any input change will be lost. When I want to give up, I noticed the CreateColumnset virtual method: protected virtual arraylist createColumnour (PagedDataSource DataSource,
Bool UsedataSource
The method is part of the Microsoft .NET framework and does not add any instructions, because Microsoft thinks the user does not try to use it directly. I personally, I believe that for a rewritable method, keep it not used is quite difficult. So I will continue and rewrite a code for this method. I don't know what the method can do, but what can I do in addition to all columns needed in the DataGrid, what can be used to name CreateColumnset? The first method I wrote is a very careful way: protected override arraylist createColumnour, Bool Usedatasource
{
ArrayList A;
A = base.createcolumnt (DataSource, UsedataSource);
Return A;
} I set up a breakpoint and run this code, and the ArrayList returned by the base method contains the DataGridColumn object and any changes entered at this time are reacted in the generated HTML. The returned array is correct and consistent with the columns set in AutogenerateColumns. Figure 6 shows the final version of CreateColumnset after overwriting. First, you retrieve columns, then sort them based on ColumnOrder properties. Sort an object array requires a custom comparison class (such as a comparison class defined in Figure 6). This comparison class compares two DataGridColumn objects based on its HeadeText property. DHTML behavior is the basis for consistency mechanisms. It is responsible for saving a new order when a drag and drop operation is complete in a hidden field (see Figure 7). This JavaScript code completes this work. About the processing of the header? After completion, I will give my colleague for feedback. I will soon realize that if the DataGrid will have problems when a header or a footer is available. why? Because the page header has different layouts and allows some NULL values to enter the JavaScript code, they will fail. You can use a tip to organize headers and footers to solve it in a TFOOT block. DHTML behavior onlys mobile heads and bodies. Anything in the foot will remain unchanged. Unfortunately, in ASP.NET, you can place the page header at the top of the DataGrid. This setting conflicts with the AAD block (because the page head is displayed in the first line of the table). If you don't place the uppermost page, it is displayed as the second line of the table and is treated as a boss. This leads that you will get the same runtime error, and it is best to correct with the TFOOT tag. Conversely, if you place the top page in THEAD, you must modify the DHTML behavior so that it can operate on the real form head without just in the first line. That is, you must force the render method of DataGrid to generate tag text according to the following specification:
Pager TR>
Column 1 TD>
Column 2 TD> TR>
THEAD>
Some TD>
Data TD> TR>
More TD>
INFO TD> TR>
tbody>
footer tr>
Pager tr> tfoot>
table> This behavior will need to check how many children on the client THEAD, and select the second line when the original table contains a top page. This information passes to the client through a new attribute HastopMostPager. = "HastopMostPager ==" True ")
Headrow = element.thead.children [1];
Else
Headrow = element.thead.children [0]; The last version of the render method is too long, inconvenient in this display, you can get the final code to get the last related DataGrid drag and drop, please remember that you can use any standard column, Including template columns about sorting? If DataGrid supports sorting, a rated sequence of sequence will be not only ordinary text, but consists of HTML elements, usually an anchor label. Use the DHTML behavior of this column you know how to get the text within it. It will be used to get the inner text of clicking a single unit and automatically remove any HTML format. Now let you know how to build client sorting capabilities. A powerful component -sort.htc behavior is proved in Dave Massy columns. This behavior intercepts any click on the table head and sorted based on the value found in the column. This behavior tracks the column of the last click, and when you click this column again, it will follow. In addition, an illustration will be added to the list to indicate the race sequence and its sorting direction. Figure 8 shows a DataGrid that uses this behavior. Graphical is a "3" (dynamically established span tag) of font for WINGDINGS. Figure 8 can be sorted by DataGrid Sort.htc behavior captures the onContentReady event, and add some initialization and add a handle to its OnClick event for each unit in the table head. When the table is set in the client, all units have an empty graph and its order is the default value. When the user is sorted by a particular column, the contents of the column will be sorted. Note that the client's sort will be plain text. If you want to sort by column, use the default server-side sorting mechanism provided by DataGrid control. Only the currently displayed record set is sorted by the server side by a named EnableClientSort property, it is almost equivalent to EnableColumNDRAG and allows the two behaviors to be allowed by adding sort.htl to behavior. These two behaviors (Behavior ) Can run well. If you are only satisfied with the client sort, it can be said to be completely completed. This behavior is sorted in the table and the sort will be invalid when the next refresh is refreshed. The client and server sorting can be supported on the same table. When the user is sorted by a server-side column (see the ID column in Figure 8), the page will be refreshed and triggered a server-side event to the DataGrid. When used to click any other columns, the sort will occur on the client. This version of Sort.htc component supports sorting on all columns. You can improve this component so that it accepts only in some columns to support sorting. Is there a way to let the client sorted? Of course, you can build the second hidden field and use the sort.htc component to assign the expression on the server to the hidden field. A good idea is a good idea, in fact, this is not something that is on the client, you don't know any information of the column displayed on the screen. The information you only know is that the header or index information stored in the hidden field and the flag information (ascending or descending order) indicating the sorting. At the server side, this information is difficult to grasp. First, I try to sort the data source based on the text. The data source bundled to the DataGrid can be any object of the IENUMERABLE interface. Unless you limit to some universal ADO.NET objects. But the biggest challenge is still sorting. If you want to provide the user as the same line order as the information generated by the client, you must sort all the data objects in the data source in text. But the data source is a collection of objects, such as dates, strings, and values defined in the format. To make sure you get the same order in the client, you must first convert any object for any object to its mark. The most important way to explore the render method, sort after generating the HTML line.
I didn't do this, but I bet, use some of the regular expressions and a custom comparison class, you can sort the HTML string representing a table. To resolve this issue, I chose other methods. I use hidden fields to track the sorting expressions used by the user last time. This information is not used in the server side. On the client, behavior read the contents of the hidden field and reinitialize the table accordingly. The following line (in the render method) makes this method possible: IF (enableclientsort) {
} When the behavior is initialized, the table information is partially displayed in the client in addition to the default manner. In this initialization phase, behavior will change the structure of the table and refresh. But this series of operations produces annoying flashing. In order to solve this problem, a table package created for DataGrid is set to Hidden in the
tab and set it Visibility to Hidden. This way, when the page is first displayed, the browser will reserve space for the table but does not display. When the behavior completes its sort, it retrieves the
tab in the DHTML object model and opens its Visibility. This behavior will identify the
summary of DataGrid and DHTML through a clear ID. There are many advantages to users. But as you can see, you need to do some work to make DataGrid to achieve anything you want to do. If you think this little exercise is useful to you, you can download the source code and tell me your results. Send problems and suggestions to Dino Author DINO Esposito is a lecturer and consultant in Rome, Italy. Also used by Microsoft ASNET (MICROSOFT Press, 2003), he uses most of its time for ADO.NET and ASP.NET teaching and speeches. Can contact him via cutting@microsoft.com. This article comes from the January 2004 journal of MSDN Magazine, you can get through local newsstands, or best subscriptions.