This is a migrated thread and some comments may be shown as answers.

Custom Sorting - can't remove .rgSorted class

3 Answers 206 Views
Grid
This is a migrated thread and some comments may be shown as answers.
William
Top achievements
Rank 1
William asked on 18 Jun 2010, 07:48 PM
I have a radgrid that is built dynamically based on fields a user drops into a panel on my page. Each time a user adds a new field to the radgrid a datalist above the grid is rebound and lists all of the fields that are currently in the grid. I don't want the users to be able to sort the radgrid columns by clicking headers, instead each field in the datalist has three corresponding linkbuttons: Sort Ascending, Sort Descending and Clear Sort.

For Example:
Invoice Date
Sort Ascending | Sort Descending | Clear Sort
Invoice Number
Sort Ascending | Sort Descending | Clear Sort

The logic all works fine, except that when a user clicks the "Clear Sort" button for any column the sorted class (.rgSorted) for that column is never removed. So even though the column is no longer sorted, it is still styled like it still is. I thought by simply removing that column from the GridSortExpressionCollection this would also remove the class, but that is obviously not the case.

How can I get rid of the class .rgSorted when a GridSortExpression is removed from the GridSortExpressionCollection?


3 Answers, 1 is accepted

Sort by
0
Veli
Telerik team
answered on 22 Jun 2010, 01:33 PM
Hi William,

Do you call Rebind() after removing a sort expression? You need to rebind the grid when adding and removing expressions. If this doesn't help, and you are using AJAX, try disabling all AJAX on your page and see if it makes any difference.

Regards,
Veli
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
William
Top achievements
Rank 1
answered on 25 Jun 2010, 07:21 PM
Thanks Veli,

I got this working, but now requirements have changed a bit and I ran into a much bigger stumbling block. All of the columns in the grid are now GridTemplateColumns, built implementing the ITemplate interface. Each column's header is built out as a template also. The header text is actually a link button that, when clicked, expands a menu of options (sorting, changing the colunm name, etc...) below the header. It works like a drop down menu...

I can't seem to wire up an event handler to any of the buttons inside the expandable menu. First I tried adding the event handler while the header is being built, then I tried adding an "onclick" attribute that calls an ajax event that will in turn fire a method in the code behind, I've even added an event handler to each button in the ItemCreated event. The result is ALWAYS the same... I click a button, lose all of the content in the grid and the event that should have fired is never touched.

So my question is simple: for a grid that is built programatically, how can I get an event handler wired to a button in the header and make sure it will actually fire? Please keep in mind that the controls that are added to the header are bulit out in a class away outside the current page instance and I do need to access members of the current page instance once the button event is fired.

This is the method in my ReportManager.cs file that builds the grid. It is called in the RowDrop event of another grid that contains a list of all the possible fields a user can add to their report.
        public static RadGrid BuildReportGrid(List<ReportFieldData> Fields, RadGrid ReportGrid) 
        { 
            ReportGrid.MasterTableView.Columns.Clear(); 
 
            foreach(ReportFieldData fd in Fields) 
            { 
                GridTemplateColumn gtc = new GridTemplateColumn(); 
                gtc.ItemTemplate = new ReportGridItemTemplate(fd); 
                gtc.HeaderTemplate = new ReportGridHeaderTemplate(fd); 
 
                gtc.DataField = fd.FieldName; 
                gtc.SortExpression = fd.FieldName; 
                gtc.UniqueName = fd.ReportFieldID.ToString(); 
 
                //if (fd.FieldType.ToLower().Contains("money")) 
                //    gtc.DataFormatString = "{0:c}"; 
                //else if (fd.FieldType.ToLower().Contains("datetime")) 
                //    gtc.DataFormatString = "{0:MM/dd/yyyy}"; 
 
                ReportGrid.MasterTableView.Columns.Add(gtc); 
            } 
 
            return ReportGrid; 
        } 

Here are my 2 template builder classes, one for the Column itself and one for the column's header. If you scroll down the btnAscending, you will see the various attempts at binding some kind of event handler to the button:
    public class ReportGridItemTemplate : ITemplate 
    { 
        protected Label lblLabel; 
        private ReportFieldData rfdFieldData; 
 
        public ReportGridItemTemplate(ReportFieldData FieldData) 
        { 
            rfdFieldData = FieldData; 
        } 
 
        public void InstantiateIn(Control container) 
        { 
            lblLabel = new Label(); 
            lblLabel.ID = "lbl"
            lblLabel.DataBinding += new EventHandler(lblLabel_DataBinding); 
 
            container.Controls.Add(lblLabel); 
        } 
 
        private void lblLabel_DataBinding(object sender, EventArgs e) 
        { 
            Label lblLabel = (Label)sender; 
            GridDataItem container = (GridDataItem)lblLabel.NamingContainer; 
            lblLabel.Text = ((DataRowView)container.DataItem)[rfdFieldData.FieldName].ToString(); 
        } 
    } 
     
    public class ReportGridHeaderTemplate : ITemplate 
    { 
        protected HtmlAnchor aOpenPanel; 
        protected LinkButton btnAscending; 
        protected LinkButton btnDescending; 
        protected LinkButton btnNoSort; 
        protected LinkButton btnLabel; 
        protected ImageButton btnRemove; 
        protected TextBox txtNewFieldName; 
        protected Button btnSaveFieldName; 
        protected RequiredFieldValidator rfvNewFieldName; 
        protected ValidationSummary vldSummary; 
 
        private ReportFieldData rfdFieldData; 
 
        public ReportGridHeaderTemplate(ReportFieldData FieldData) 
        { 
            rfdFieldData = FieldData; 
        } 
 
        public void InstantiateIn(Control container) 
        { 
            aOpenPanel = new HtmlAnchor(); 
            aOpenPanel.ID = "aOpenPanel" + rfdFieldData.ReportFieldID.ToString(); 
            aOpenPanel.InnerHtml = rfdFieldData.FieldDisplayName; 
            aOpenPanel.HRef = "JavaScript:OpenEditPanel(" + rfdFieldData.ReportFieldID.ToString() + ");"
 
            container.Controls.Add(aOpenPanel); 
 
            Literal litHTML = new Literal(); 
            litHTML.ID = "litWrapperOpenTag" + rfdFieldData.ReportFieldID.ToString(); 
            litHTML.Text = "<div style=\"position:relative;\">"
 
            container.Controls.Add(litHTML); 
 
            litHTML = new Literal(); 
            litHTML.ID = "litSlidePanelOpenTag" + rfdFieldData.ReportFieldID.ToString(); 
            litHTML.Text = "<div class=\"slidepanel\" id=\"div" + rfdFieldData.ReportFieldID.ToString() + "\" style=\"top:5px !important; left:0 !important; background-color:#dedede !important; border-top:none !important;\">"
 
            container.Controls.Add(litHTML); 
 
            litHTML = new Literal(); 
            litHTML.ID = "litCloseSlidePanel" + rfdFieldData.ReportFieldID.ToString(); 
            litHTML.Text = "<div style=\"float:right; padding:1px 0 0 0;\"><a style=\"cursor:pointer;\" onclick=\"CloseEditPanel('" + rfdFieldData.ReportFieldID.ToString() + "');\"><img src=\"../images/cross-small.png\" title=\"Edit Field Name\" /></a></div>"
 
            container.Controls.Add(litHTML); 
 
            litHTML = new Literal(); 
            litHTML.ID = "litFieldLabel" + rfdFieldData.ReportFieldID.ToString(); 
            litHTML.Text = "<b>Enter a New Field Name:</b>"
 
            container.Controls.Add(litHTML); 
 
            txtNewFieldName = new TextBox(); 
            txtNewFieldName.ID = "txtNewFieldName" + rfdFieldData.ReportFieldID.ToString(); 
            txtNewFieldName.ValidationGroup = rfdFieldData.ReportFieldID.ToString(); 
            txtNewFieldName.Columns = 32; 
            txtNewFieldName.CssClass = "editfield"
 
            container.Controls.Add(txtNewFieldName); 
 
            btnSaveFieldName = new Button(); 
            btnSaveFieldName.ID = "btnSaveFieldName" + rfdFieldData.ReportFieldID.ToString(); 
            btnSaveFieldName.Text = "Save"
            btnSaveFieldName.CommandName = "edit"
            btnSaveFieldName.CommandArgument = rfdFieldData.ReportFieldID.ToString(); 
            btnSaveFieldName.ValidationGroup = rfdFieldData.ReportFieldID.ToString(); 
 
            container.Controls.Add(btnSaveFieldName); 
 
            rfvNewFieldName = new RequiredFieldValidator(); 
            rfvNewFieldName.ID = "rfvNewFieldName" + rfdFieldData.ReportFieldID.ToString(); 
            rfvNewFieldName.Display = ValidatorDisplay.Dynamic; 
            rfvNewFieldName.ControlToValidate = "txtNewFieldName" + rfdFieldData.ReportFieldID.ToString(); 
            rfvNewFieldName.ValidationGroup = rfdFieldData.ReportFieldID.ToString(); 
            rfvNewFieldName.Text = "<img src=\"../images/arrow-turn-090_red.png\" /> New Field Name is Required."
 
            container.Controls.Add(rfvNewFieldName); 
 
            vldSummary = new ValidationSummary(); 
            vldSummary.ID = "vldSummary" + rfdFieldData.ReportFieldID.ToString(); 
            vldSummary.ValidationGroup = rfdFieldData.ReportFieldID.ToString(); 
            vldSummary.DisplayMode = ValidationSummaryDisplayMode.SingleParagraph; 
            vldSummary.Visible = false
 
            container.Controls.Add(vldSummary); 
 
            btnAscending = new LinkButton(); 
            btnAscending.ID = "btnAscending" + rfdFieldData.ReportFieldID.ToString(); 
            btnAscending.Text = "Sort Asc"
            btnAscending.CommandName = "asc"
            btnAscending.ToolTip = "Sort Column Ascending"
            btnAscending.CommandArgument = rfdFieldData.ReportFieldID.ToString(); 
            btnAscending.Click += new EventHandler(btnAscending_Click); 
            //btnAscending.Attributes.Add("onclick", "InvokeRequest(" + rfdFieldData.ReportFieldID.ToString() + ", '" + container.ClientID.Remove(container.ClientID.Length - 5) + btnAscending.ID + "');"); 
            //btnAscending.Attributes.Add("onclick", "ButtonClick();"); 
 
            container.Controls.Add(btnAscending); 
 
            litHTML = new Literal(); 
            litHTML.ID = "litFirstSpacer" + rfdFieldData.ReportFieldID.ToString(); 
            litHTML.Text = "&nbsp;|&nbsp;"
 
            container.Controls.Add(litHTML); 
 
            btnDescending = new LinkButton(); 
            btnDescending.ID = "btnDescending" + rfdFieldData.ReportFieldID.ToString(); 
            btnDescending.Text = "Sort Desc"
            btnDescending.CommandName = "desc"
            btnDescending.ToolTip = "Sort Column Descending"
            btnDescending.CommandArgument = rfdFieldData.ReportFieldID.ToString(); 
 
            container.Controls.Add(btnDescending); 
 
            litHTML = new Literal(); 
            litHTML.ID = "litSecondSpacer" + rfdFieldData.ReportFieldID.ToString(); 
            litHTML.Text = "&nbsp;|&nbsp;"
 
            container.Controls.Add(litHTML); 
 
            btnNoSort = new LinkButton(); 
            btnNoSort.ID = "btnNoSort" + rfdFieldData.ReportFieldID.ToString(); 
            btnNoSort.Text = "No Sort"
            btnNoSort.CommandName = "none"
            btnNoSort.ToolTip = "Clear Column Sort"
            btnNoSort.CommandArgument = rfdFieldData.ReportFieldID.ToString(); 
 
            container.Controls.Add(btnNoSort); 
 
            litHTML = new Literal(); 
            litHTML.ID = "litSlidePanelCloseTag" + rfdFieldData.ReportFieldID.ToString(); 
            litHTML.Text = "</div>"
 
            container.Controls.Add(litHTML); 
 
            litHTML = new Literal(); 
            litHTML.ID = "litWrapperCloseTag" + rfdFieldData.ReportFieldID.ToString(); 
            litHTML.Text = "</div>"
 
            container.Controls.Add(litHTML); 
        } 
 
        public void btnAscending_Click(object sender, EventArgs e) 
        { 
            LinkButton bAscending = (LinkButton)sender; 
            string sFieldName = Data.CurrentContext.Report_Fields.Where(rf => rf.ReportFieldID == Convert.ToInt32(bAscending.CommandArgument)).SingleOrDefault().FieldName; 
 
          
 
            if (String.IsNullOrEmpty(sFieldName)) 
            { 
                //ReportManager.BuildReportGrid(lFields, rgReportGrid); 
                //GridManager.UpdateSortOrder(rgReportGrid.MasterTableView.SortExpressions, sFieldName, "Ascending"); 
                //ReportManager.UpdateReportFieldSortOrder(Convert.ToInt32(bAscending.CommandArgument), "Ascending"); 
                //rgReportGrid.Rebind(); 
            } 
        } 
    } 

0
Veli
Telerik team
answered on 28 Jun 2010, 02:21 PM
Hi William,

Firing custom events from RadGrid items is actually easier than it looks. RadGrid supports the event bubbling mechanism for databound controls. Particularly, any custom command from inside grid items bubbles to RadGrid and RadGrid fires its ItemCommand event. So, you just need to set CommandName to your sort buttons.  The command action itself can be handled by checking for the custom command name:

protected void RadGrid1_ItemCommand(object source, GridCommandEventArgs e)
{
    if (e.CommandName == "MyCustomCommand")
    {
        //handle MyCustomCommand here
    }
}

In your case, wiring the Click handlers of the command buttons in the header is not required in your case. In fact, the most important part in your scenario seems to be properly recreating the grid structure. As you are loading the grid dynamically on postback, you need to make sure the same grid structure is properly recreated on postback.

Sincerely yours,
Veli
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Tags
Grid
Asked by
William
Top achievements
Rank 1
Answers by
Veli
Telerik team
William
Top achievements
Rank 1
Share this question
or