Hi,
I have two levels of grouping in my RadGrid:
<telerik:RadGrid ID="uxByAgeAndGenderGrid" runat="server" AutoGenerateColumns="false" CssClass="gridAlternatingRows" |
OnItemDataBound="uxByAgeAndGenderGrid_OnItemDataBound" OnNeedDataSource="uxByAgeAndGenderGrid_OnNeedDataSource"> |
<MasterTableView GroupLoadMode="Client" ShowGroupFooter="true" HeaderStyle-Font-Bold="true" ShowFooter="true"> |
<GroupByExpressions> |
<telerik:GridGroupByExpression> |
<SelectFields> |
<telerik:GridGroupByField FieldName="RequestedGender" HeaderText=" " HeaderValueSeparator="" /> |
</SelectFields> |
<GroupByFields> |
<telerik:GridGroupByField FieldName="RequestedGender" /> |
</GroupByFields> |
</telerik:GridGroupByExpression> |
<telerik:GridGroupByExpression> |
<SelectFields> |
<telerik:GridGroupByField FieldName="RequestedMinAge" HeaderText=" " HeaderValueSeparator="" /> |
</SelectFields> |
<GroupByFields> |
<telerik:GridGroupByField FieldName="RequestedMinAgeRank" /> |
</GroupByFields> |
</telerik:GridGroupByExpression> |
</GroupByExpressions> |
<Columns> |
<telerik:GridBoundColumn DataField="Status" HeaderText="Status" SortExpression="StatusRank"> |
</telerik:GridBoundColumn> |
<telerik:GridBoundColumn DataField="NewCount" HeaderText="New invitations" Aggregate="Sum" FooterText="Total: "> |
</telerik:GridBoundColumn> |
<telerik:GridBoundColumn DataField="ReinviteCount" HeaderText="Re-invite invitations" Aggregate="Sum" FooterText="Total: "> |
</telerik:GridBoundColumn> |
<telerik:GridBoundColumn DataField="AskedForCount" HeaderText="Asked For invitations" Aggregate="Sum" FooterText="Total: "> |
</telerik:GridBoundColumn> |
<telerik:GridBoundColumn DataField="TotalCount" HeaderText="Total" Aggregate="Sum" FooterText="Grand total: "> |
</telerik:GridBoundColumn> |
</Columns> |
</MasterTableView> |
</telerik:RadGrid> |
And I would like to have both levels of grouping collapsed by default. I've tried the following property on the MasterTableView:
GroupsDefaultExpanded="false" |
But this only seems to collapse the top grouping level. When you expand on of the top groups, all of its subgroups open up expanded!
So next, I tried the following in the OnLoad method, as instructed by http://www.telerik.com/help/aspnet-ajax/grdcollapseallitemsongrouping.html:
if (!IsPostBack) |
{ |
uxByAgeAndGenderGrid.Rebind(); |
foreach (GridItem item in uxByAgeAndGenderGrid.MasterTableView.Controls[0].Controls) |
{ |
if (item is GridGroupHeaderItem) |
{ |
item.Expanded = false; |
} |
} |
} |
But I get the following error:
Server Error in '/' Application. |
StartIndex cannot be less than zero. |
Parameter name: startIndex |
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. |
Exception Details: System.ArgumentOutOfRangeException: StartIndex cannot be less than zero. |
Parameter name: startIndex |
Source Error: |
Line 37: if (item is GridGroupHeaderItem) |
Line 38: { |
Line 39: item.Expanded = false; |
Line 40: } |
Line 41: } |
Source File: C:\VS\Flive\Main\Source\FliveSolution\Freshair.Flive\Experiences\FriendlyTown\FtByTheNumbers.aspx.cs Line: 39 |
Stack Trace: |
[ArgumentOutOfRangeException: StartIndex cannot be less than zero. |
Parameter name: startIndex] |
System.String.Remove(Int32 startIndex) +6576122 |
Telerik.Web.UI.GridGroupHeaderItem.GroupFooterByHeaderIndexAndSequenceNumber(String groupIndex, Int32 seqNum) +202 |
Telerik.Web.UI.GridGroupHeaderItem.SetVisibleChildren(Boolean value) +794 |
Telerik.Web.UI.GridItem.set_Expanded(Boolean value) +126 |
Freshair.Flive.Experiences.FriendlyTown.FtByTheNumbersPage.OnLoad(EventArgs e) in C:\VS\Flive\Main\Source\FliveSolution\Freshair.Flive\Experiences\FriendlyTown\FtByTheNumbers.aspx.cs:39 |
System.Web.UI.Control.LoadRecursive() +71 |
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3048 |
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1 |
The OnNeedDataSource looks like this:
protected void uxByAgeAndGenderGrid_OnNeedDataSource(Object sender, GridNeedDataSourceEventArgs e) |
{ |
Int32 programYear = DateTime.Today.GetChildApplicationProgramYear(); |
var childrenWhoParticipatedInPreviousYears = |
from child in Ctx.Persons |
join vep in Ctx.ViewExperienceParticipations on child.PersonId equals vep.PersonId |
join status in Ctx.ExperienceEligibilityPersonParticipationStatus on vep.CurrentStatusId equals status.ExperienceEligibilityPersonParticipationStatusId |
join ee in Ctx.ExperienceEligibilities on vep.ExperienceEligibilityId equals ee.ExperienceEligibilityId |
join exp in Ctx.Experiences on ee.ExperienceId equals exp.ExperienceId |
join et in Ctx.ExperienceTypes on exp.ExperienceTypeId equals et.ExperienceTypeId |
where !status.NullifiesParticipation |
where status.ExperienceEligibilityPersonParticipationStatusId != 1 // Other than Invited |
where exp.FromDate.Value.Year < programYear |
select new |
{ |
child.PersonId, |
exp.HostingHouseholdId |
}; |
List<String> statusRank = new List<String>(); |
statusRank.Add("Matched"); |
statusRank.Add("Open"); |
statusRank.Add("Invited"); |
statusRank.Add("Placed"); |
statusRank.Add("Refused"); |
statusRank.Add("Not Found"); |
statusRank.Add("Excused"); |
statusRank.Add("Proposed New Dates"); |
statusRank.Add("Must Approve Trip Dates"); |
statusRank.Add("Child proposed new dates"); |
statusRank.Add("Child must approve dates"); |
statusRank.Add("Didn't Show"); |
statusRank.Add("Attended"); |
statusRank.Add("Returned Early"); |
statusRank.Add("Transferred Out"); |
statusRank.Add("Canceled"); |
statusRank.Add("Closed by child"); |
statusRank.Add("Withdrawn by host"); |
statusRank.Add("Change In Progress"); |
List<String> ageRank = new List<String>(); |
ageRank.Add("0 to 5"); |
ageRank.Add("6 to 8"); |
ageRank.Add("9 to 10"); |
ageRank.Add("11 to 12"); |
ageRank.Add("Over 13"); |
ageRank.Add("Unknown"); |
DateTime today = DateTime.Today; |
var invitations = |
(from exp in Ctx.Experiences |
join et in Ctx.ExperienceTypes on exp.ExperienceTypeId equals et.ExperienceTypeId |
join ec in Ctx.ExperienceCategories on et.ExperienceCategoryId equals ec.ExperienceCategoryId |
join vee in Ctx.ViewActiveEligibilityByExperiences on exp.ExperienceId equals vee.ExperienceId |
join ee in Ctx.ExperienceEligibilities on vee.ExperienceEligibilityId equals ee.ExperienceEligibilityId |
join reqPerson in Ctx.Persons on ee.PersonId equals reqPerson.PersonId into reqPersons |
from reqPerson in reqPersons.DefaultIfEmpty() |
join part in Ctx.ViewExperienceParticipations on ee.ExperienceEligibilityId equals part.ExperienceEligibilityId into parts |
from part in parts.DefaultIfEmpty() |
join person in Ctx.Persons on part.PersonId equals person.PersonId into persons |
from person in persons.DefaultIfEmpty() |
join status in Ctx.ExperienceEligibilityPersonParticipationStatus on part.CurrentStatusId equals status.ExperienceEligibilityPersonParticipationStatusId into statuses |
from status in statuses.DefaultIfEmpty() |
join searchParam in Ctx.ViewInvitationEligibilityParameters on ee.SearchId equals searchParam.SearchId into searchParams |
from searchParam in searchParams.DefaultIfEmpty() |
where exp.FromDate.GetValueOrDefault(new DateTime(1877, 1, 1)).Year == programYear |
where et.ExperienceCategoryId == 1 |
where part == null || part.ExperienceEligibilityPersonParticipationTypeId == 1 // Child |
where person == null || person.PersonId != 30190 |
select new |
{ |
RequestedGender = reqPerson == null ? (searchParam == null ? "Unknown" : |
(searchParam.Gender == null ? "Either a boy or a girl" : |
(searchParam.Gender == "M" ? "Only a boy" : "Only a girl"))) : |
(reqPerson.Gender == null ? "Unknown" : (reqPerson.Gender == "M" ? "Only a boy" : "Only a girl")), |
RequestedMinAge = reqPerson == null ? (searchParam == null ? -1 : |
(searchParam.MinAge == null ? -1 : searchParam.MinAge)) : |
(reqPerson.BirthDate == null ? -1 : Ctx.FuncGetAge(reqPerson.BirthDate, today)), |
IsNew = ee.SearchId != null ? true : false, |
IsReinvite = ee.PersonId == null ? false : |
(childrenWhoParticipatedInPreviousYears.Where(p => p.PersonId == ee.PersonId && p.HostingHouseholdId == exp.HostingHouseholdId).Count() > 0 ? true : false), |
Program = ec.Name, |
StatusId = status == null ? 0 : status.ExperienceEligibilityPersonParticipationStatusId, |
IsWithdrawn = exp.IsCanceled |
}).ToArray(); |
var invitations2 = |
(from invitation in invitations |
group new |
{ |
IsNew = invitation.IsNew, |
IsReinvite = invitation.IsReinvite |
} by new |
{ |
RequestedGender = invitation.RequestedGender, |
RequestedMinAge = invitation.RequestedMinAge < 0 ? "Unknown" : |
(invitation.RequestedMinAge < 6 ? "0 to 5" : |
(invitation.RequestedMinAge < 9 ? "6 to 8" : |
(invitation.RequestedMinAge < 11 ? "9 to 10" : |
(invitation.RequestedMinAge < 13 ? "11 to 12" : "Over 13")))), |
Status = invitation.IsWithdrawn ? "Withdrawn by host" : FtLogicController.GetInvitationStatusByCurrentParticipationStatus(invitation.StatusId).GetStatusText() |
} into grouping |
select grouping).ToArray(); |
var invitationsToBind = |
from grouping in invitations2 |
select new |
{ |
RequestedGender = grouping.Key.RequestedGender, |
RequestedMinAge = grouping.Key.RequestedMinAge, |
RequestedMinAgeRank = ageRank.IndexOf(grouping.Key.RequestedMinAge), |
Status = grouping.Key.Status, |
StatusRank = statusRank.IndexOf(grouping.Key.Status), |
NewCount = grouping.Count(p => p.IsNew), |
ReinviteCount = grouping.Count(p => p.IsReinvite), |
AskedForCount = grouping.Count(p => !p.IsReinvite && !p.IsNew), |
TotalCount = grouping.Count() |
}; |
uxByAgeAndGenderGrid.GroupingSettings.RetainGroupFootersVisibility = true; |
uxByAgeAndGenderGrid.DataSource = invitationsToBind.OrderBy(p => p.StatusRank); |
uxInvitationsToBeFilled.Text = invitationsToBind.Where(p => p.Status == "Open").Sum(p => p.TotalCount).ToString(); |
uxMatchedInvitationsNotYetDeparted.Text = invitationsToBind.Where(p => p.Status == "Matched").Sum(p => p.TotalCount).ToString(); |
} |
Any ideas?
Many thanks,
Jake
(And in case you're wondering what in the world is going on here, this is a report of invitations tendered by volunteer host families for The Fresh Air Fund - www.freshair.org.)