Hello,
I'm using DataGridView and design a dynamic grid view with GridViewToggleRowDetailsColumn. so far I can register an event at first level like this:
my datatemplate look like this
however, the toggle event not fire at the second level. It just can happen in first level. so how can i make it happen if i wish every toggle button can call the registered event at first level?
here is whole cs file.
I'm using DataGridView and design a dynamic grid view with GridViewToggleRowDetailsColumn. so far I can register an event at first level like this:
view.RowDetailsVisibilityChanged += new EventHandler<GridViewRowDetailsEventArgs>(view_RowDetailsVisibilityChanged2);private DataTemplate CreateNewDataTemplate() { string rtnXaml = string.Empty; string baseXaml = @"<DataTemplate x:Key='RowDetailsTemplate' xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:telerik='http://schemas.telerik.com/2008/xaml/presentation' xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""> <telerik:RadGridView Name='SubListGrid{KEYTYPE}' ItemsSource='{Binding DetailList}' AutoGenerateColumns='False' CanUserSortGroups='False' CanUserInsertRows='False' CanUserFreezeColumns='False' CanUserDeleteRows='False' ShowGroupPanel='False' IsReadOnly='true'> <telerik:RadGridView.Columns> {TOGGLEROWDETAILCOLUMN} <telerik:GridViewDataColumn Header='{HEADER}' DataMemberBinding='{Binding GroupKey}' TextAlignment='Center'/> <telerik:GridViewDataColumn Header='人數' DataMemberBinding='{Binding Count}' TextAlignment='Right' DataFormatString = '{}{0:N0}'/> <telerik:GridViewDataColumn Header='百分比' DataMemberBinding='{Binding Percentage}' DataFormatString = '{}{0:f2}%' TextAlignment='Right'/> </telerik:RadGridView.Columns> {SUBTEMPLATE} </telerik:RadGridView> </DataTemplate>"; string subLevelXaml = @"<telerik:RadGridView.RowDetailsTemplate> <DataTemplate x:Key='RowDetailsTemplate'> <telerik:RadGridView Name='SubListGrid{KEYTYPE}' ItemsSource='{Binding DetailList}' AutoGenerateColumns='False' CanUserSortGroups='False' CanUserInsertRows='False' CanUserFreezeColumns='False' CanUserDeleteRows='False' ShowGroupPanel='False' IsReadOnly='true'> <telerik:RadGridView.Columns> {TOGGLEROWDETAILCOLUMN} <telerik:GridViewDataColumn Header='{HEADER}' DataMemberBinding='{Binding GroupKey}' TextAlignment='Center'/> <telerik:GridViewDataColumn Header='人數' DataMemberBinding='{Binding Count}' TextAlignment='Right' DataFormatString = '{}{0:N0}'/> <telerik:GridViewDataColumn Header='百分比' DataMemberBinding='{Binding Percentage}' DataFormatString = '{}{0:f2}%' TextAlignment='Right'/> </telerik:RadGridView.Columns> {SUBTEMPLATE} </telerik:RadGridView> </DataTemplate> </telerik:RadGridView.RowDetailsTemplate>"; foreach (ReportType type in command) { if (command.First().Equals(type)) { if (ReportType.Location.Equals(type)) rtnXaml = baseXaml.Replace("{KEYTYPE}", "Area").Replace("{HEADER}", "縣/市"); continue; } if (rtnXaml.Equals(string.Empty)) { rtnXaml = baseXaml.Replace("{KEYTYPE}", type.ToString()).Replace("{HEADER}", HeaderKeyDictionary[type.ToString()].ToString()); } else { string subXaml = subLevelXaml.Replace("{KEYTYPE}", type.ToString()).Replace("{HEADER}", HeaderKeyDictionary[type.ToString()].ToString()); rtnXaml = rtnXaml.Replace("{TOGGLEROWDETAILCOLUMN}", "<telerik:GridViewToggleRowDetailsColumn/>").Replace("{SUBTEMPLATE}", subXaml); } if (ReportType.Location.Equals(type)) { string subXaml = subLevelXaml.Replace("{KEYTYPE}", "Area").Replace("{HEADER}", "縣/市"); rtnXaml = rtnXaml.Replace("{TOGGLEROWDETAILCOLUMN}", "<telerik:GridViewToggleRowDetailsColumn/>").Replace("{SUBTEMPLATE}", subXaml); } } rtnXaml = rtnXaml.Replace("{TOGGLEROWDETAILCOLUMN}", string.Empty).Replace("{SUBTEMPLATE}", string.Empty); System.Text.UTF8Encoding myEncoder = new System.Text.UTF8Encoding(); byte[] bytes = myEncoder.GetBytes(rtnXaml); MemoryStream ms = new MemoryStream(bytes); DataTemplate dt = (DataTemplate)XamlReader.Load(ms); return dt; }here is whole cs file.
using System;using System.Collections;using System.Collections.Generic;using System.IO;using System.Linq;using System.Threading;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Markup;using System.Windows.Threading;using Friendo.Backstage.Base;using Friendo.Backstage.BusinessWCFReference;using Friendo.Backstage.Model;using Friendo.Backstage.Support.Structure;using Friendo.Backstage.View;using Microsoft.Practices.EnterpriseLibrary.Caching;using Telerik.Windows.Controls;using Telerik.Windows.Controls.Charting;using Telerik.Windows.Data;using Telerik.Windows.Controls.GridView;namespace Friendo.Backstage.ViewModel{ class MemberAnalysisVM : GridMaintenceVM<MemberAnalysisModel, MemberAnalysisDashboard>, IViewModel { Hashtable HeaderDictionary = new Hashtable(); Hashtable HeaderKeyDictionary = new Hashtable(); ICacheManager cacheManager = CacheFactory.GetCacheManager(); Queue<ReportType> command = new Queue<ReportType>(); enum ReportType { None=0,Gender,Age,Area,Location } class AggregateModel { public string GroupKey { get; set; } public int Count { get; set; } public float Percentage { get; set; } public ReportType NextType { get; set; } public ArrayList DetailList { get; set; } } class AreaModel { public string Area { get; set; } public int Count { get; set; } public float Percentage { get; set; } public List<MemberAnalysisDetailModel> CountriesList { get; set; } } AuthToken token = AuthToken.GetInstance(); public MemberAnalysisVM() { this.Initialize(); } void UpdateMemberCount() { SetMemberCount(); UpdateMemberCountRuntime(); } void UpdateMemberCountRuntime() { DispatcherTimer t = new DispatcherTimer(); int sleepTime = 60 * 1000 * 1000; t.Tick += new EventHandler(t_Tick); t.Interval = new TimeSpan(sleepTime); t.Start(); } void t_Tick(object sender, EventArgs e) { SetMemberCount(); } private void SetMemberCount() { using (BusinessWCFReference.BusinessClient client = new BusinessWCFReference.BusinessClient()) { BusinessWCFReference.GetThirdPartyMemberCountsInput input = new BusinessWCFReference.GetThirdPartyMemberCountsInput() { ThirdPartyID = token.ThirdPartyID }; var output = client.GetThirdPartyMemberCounts(input); if (output.IsSuccess) { QueryView.MemberCount.Text = output.ReturnData.TotalCounts; }; var rtn = client.GetThirdPartyBasicInfo(new GetThirdPartyBasicInfoInput() { ThirdPartyID = token.ThirdPartyID }); } } private void Initialize() { QueryView.busyr.IsBusy = false; if (token == null) token = AuthToken.GetInstance(); if (string.IsNullOrEmpty(token.ThirdPartyID)) return;// TODO;補登出 if (cacheManager.GetData("Report") == null) { QueryView.busyr.IsBusy = true; Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => GetData())); } GenerateHeaderDictionary(); ShowView = new FrameView(); ShowView.AddView(QueryView); QueryView.DataContext = this; SetActiveView(QueryView); QueryView.Gender.Checked += RadioButtonClick; QueryView.Age.Checked += RadioButtonClick; QueryView.Location.Checked += RadioButtonClick; QueryView.GenderButton.Checked += CheckedButton; QueryView.AgeButton.Checked += CheckedButton; QueryView.LocationButton.Checked += CheckedButton; QueryView.GenderButton.Unchecked += GenderButton_Unchecked; QueryView.AgeButton.Unchecked += GenderButton_Unchecked; QueryView.LocationButton.Unchecked += GenderButton_Unchecked; QueryView.busyr.Cancel += new EventHandler(busyr_Cancel); UpdateMemberCount(); QueryView.busyr.IsBusy = false; } private void GenerateNewView() { if (command.Count <= 1) { ShowUI(command.FirstOrDefault()); return; } DataTemplate template = new DataTemplate(); List<AggregateModel> aggregateList = SortData(); ReportType firstKey = command.FirstOrDefault(); RadGridView view = new RadGridView() { CanUserSortGroups = false, CanUserInsertRows = false, CanUserFreezeColumns = false, CanUserDeleteRows = false, AutoGenerateColumns = false, ShowGroupPanel = false, ShowColumnFooters = true, ShowGroupFooters = true, MaxHeight = QueryView.Report.MaxHeight }; view.RowDetailsTemplate = CreateNewDataTemplate(); view.RowDetailsVisibilityChanged += new EventHandler<GridViewRowDetailsEventArgs>(view_RowDetailsVisibilityChanged2); view.Columns.Add(new GridViewToggleRowDetailsColumn()); view.Columns.Add((GridViewDataColumn)HeaderDictionary[firstKey.ToString() + "MultiSelected"]); view.Columns.Add((GridViewDataColumn)HeaderDictionary["Count"]); view.Columns.Add((GridViewDataColumn)HeaderDictionary["Percentage"]); view.ItemTemplate = template; view.ItemsSource = aggregateList; Dictionary<string, int> dictionary = aggregateList.GroupBy(p => p.GroupKey, StringComparer.OrdinalIgnoreCase).ToDictionary(g => g.Key, g => g.First().Count, StringComparer.OrdinalIgnoreCase); GeneratePieChart(dictionary); QueryView.Report.Children.Clear(); QueryView.Report.Children.Add(view); } void view_RowDetailsVisibilityChanged2(object sender, GridViewRowDetailsEventArgs e) { } void CheckedButton(object sender, RoutedEventArgs e) { ReportType mykey = (ReportType)Enum.Parse(typeof(ReportType), (string)((CheckBox)e.Source).Name.Replace("Button", string.Empty), true); if (!command.Contains(mykey)) command.Enqueue(mykey); GenerateNewView(); } void GenderButton_Unchecked(object sender, RoutedEventArgs e) { ReportType mykey = (ReportType)Enum.Parse(typeof(ReportType), (string)((CheckBox)e.Source).Name.Replace("Button", string.Empty), true); Queue<ReportType> newQueue = new Queue<ReportType>(); foreach (ReportType type in command) { if (mykey != type) newQueue.Enqueue(type); } command = newQueue; GenerateNewView(); } List<AggregateModel> SortData() { List<MemberAnalysisDetailModel> list = GetData(); ReportType nextCommand = (command.Count <= 1) ? ReportType.None : command.ToList()[command.ToList().IndexOf(command.First()) + 1]; List<AggregateModel> rtnList = new List<AggregateModel>(); switch (command.First()) { case ReportType.Gender: rtnList = list.GroupBy(w => w.Gender).Select(u => new AggregateModel { GroupKey = u.Key, Count = u.Sum(item => item.Count), DetailList = new ArrayList(u.ToList()), NextType = nextCommand }).ToList(); break; case ReportType.Age: rtnList = list.GroupBy(w => w.Age).Select(u => new AggregateModel { GroupKey = u.Key, Count = u.Sum(item => item.Count), DetailList = new ArrayList(u.ToList()), NextType = nextCommand }).ToList(); break; case ReportType.Location: rtnList = list.GroupBy(w => w.Location).Select(u => new AggregateModel { GroupKey = u.Key, Count = u.Sum(item => item.Count), DetailList = new ArrayList(u.ToList()), NextType = nextCommand }).ToList(); break; default: return new List<AggregateModel>(); } int sum = rtnList.Sum(t => t.Count); rtnList.ForEach(t => t.Percentage = (float)t.Count / (float)sum * 100); ReportType aggregateKey = nextCommand; nextCommand = (command.Last().Equals(aggregateKey)) ? ReportType.None : command.ToList()[command.ToList().IndexOf(aggregateKey) + 1]; foreach (var subList in rtnList) { List<AggregateModel> sortedAggregateList = new List<AggregateModel>(); sortedAggregateList = AggregateSublist(aggregateKey, subList.DetailList); sum = sortedAggregateList.Sum(t => t.Count); sortedAggregateList.ForEach(t => t.Percentage = (float)t.Count / (float)sum * 100); AggreateSubList(sortedAggregateList); subList.DetailList = new ArrayList(sortedAggregateList); } if(ReportType.Location.Equals(command.First())) { rtnList = GenerateAreaReportData(rtnList, nextCommand); } return rtnList; } List<AggregateModel> AggreateSubList(List<AggregateModel> target) { foreach (var subList in target) { if (!((ReportType.None.Equals(subList.NextType)))) { if ((ReportType.Location.Equals(subList.NextType)) && ((Enum.GetNames(typeof(LocationEnum)).Contains(subList.GroupKey)))) { AggreateSubList(subList.DetailList.Cast<AggregateModel>().ToList()); continue; } List<AggregateModel> list = AggregateSublist(subList.NextType, subList.DetailList); int sum = list.Sum(t => t.Count); list.ForEach(t => t.Percentage = (float)t.Count / (float)sum * 100); AggreateSubList(list); subList.DetailList = new ArrayList(list); } } return target; } List<AggregateModel> AggregateSublist(ReportType key, ArrayList detailList) { ReportType nextCommand = (command.Last().Equals(key)) ? ReportType.None : command.ToList()[command.ToList().IndexOf(key) + 1]; List<AggregateModel> rtnList = new List<AggregateModel>(); switch (key) { case ReportType.Gender: detailList.ToArray().GroupBy(w => ((MemberAnalysisDetailModel)w).Gender).Select(u => new MemberAnalysisDetailModel { Gender = u.Key, Count = u.ToList().Sum(item => ((MemberAnalysisDetailModel)item).Count) }) .ToList().ForEach(v => rtnList.Add(new AggregateModel() { GroupKey = v.Gender, Count = v.Count, DetailList = new ArrayList(detailList), NextType = nextCommand })); break; case ReportType.Age: detailList.ToArray().GroupBy(w => ((MemberAnalysisDetailModel)w).Age).Select(u => new MemberAnalysisDetailModel { Age = u.Key, Count = u.Sum(item => ((MemberAnalysisDetailModel)item).Count) }) .ToList().ForEach(v => rtnList.Add(new AggregateModel() { GroupKey = v.Age, Count = v.Count, DetailList = new ArrayList(detailList), NextType = nextCommand })); break; case ReportType.Location: rtnList = GenerateAreaReportData(detailList, nextCommand); break; default: break; } return rtnList; } void busyr_Cancel(object sender, EventArgs e) { QueryView.busyr.IsBusy = false; } void RadioButtonClick(object sender, System.Windows.RoutedEventArgs e) { DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromMilliseconds(100); timer.Tick += (s, e2) => { string itemName = ((RadioButton)e.Source).Name; var scheduler = TaskScheduler.FromCurrentSynchronizationContext(); Task.Factory.StartNew(new Action<object>(ShowUI), (ReportType)Enum.Parse(typeof(ReportType), (string)itemName, true), CancellationToken.None, TaskCreationOptions.None, scheduler); timer.Stop(); }; timer.Start(); QueryView.busyr.IsBusy = true; } private void ShowUI(object itemName) { if (itemName == null) return; switch ((ReportType)itemName) { case ReportType.Gender: Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => ShowGenderReport())); break; case ReportType.Age: Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => ShowAgeReport())); break; case ReportType.Location: Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => ShowLocationReport())); break; case ReportType.None: QueryView.Report.Children.Clear(); QueryView.PieChart.Children.Clear(); break; default: break; } return; } void GeneratePieChart(IDictionary dictionary) { QueryView.PieChart.Children.Clear(); RadChart chart = new RadChart() { Width = 500, Height = 300, FontSize = 12 }; DataSeries series = new DataSeries(); series.Definition = new PieSeriesDefinition(); foreach (string s in dictionary.Keys) { series.Add(new Telerik.Windows.Controls.Charting.DataPoint() { LegendLabel = s, YValue = Convert.ToDouble(dictionary[s]) }); } chart.DefaultView.ChartArea.DataSeries.Add(series); QueryView.PieChart.HorizontalAlignment = HorizontalAlignment.Right; QueryView.PieChart.Children.Add(chart); } private List<MemberAnalysisDetailModel> GetData() { if (token == null) token = AuthToken.GetInstance(); if (string.IsNullOrEmpty(token.ThirdPartyID)) return null;// TODO;補登出 ICacheManager cacheManager = CacheFactory.GetCacheManager(); var data = cacheManager.GetData("RowData") as ReturnMessageOfArrayOfGetThirdPartyMemberAnalyOutputIfqRiZFe; if (data == null) { using (BusinessWCFReference.BusinessClient client = new BusinessClient()) { GetThirdPartyMemberAnalyInput input = new GetThirdPartyMemberAnalyInput() { Condition = 7, ThirdPartyID = token.ThirdPartyID }; data = client.GetThirdPartyMemberAnaly(input); } cacheManager.Add("RowData", data); } List<MemberAnalysisDetailModel> reportList = cacheManager.GetData("Report") as List<MemberAnalysisDetailModel>; if (reportList == null) { reportList = new List<MemberAnalysisDetailModel>(); int count = 0; data.ReturnData.Where(t => (!string.IsNullOrEmpty(t.Age)) && (!string.IsNullOrEmpty(t.Gender)) && (!string.IsNullOrEmpty(t.Counts))).ToList() .ForEach(t => reportList.Add( new MemberAnalysisDetailModel() { Location = t.City, Age = t.Age, Gender = t.Gender, Count = int.TryParse(t.Counts, out count) ? count : 0 })); cacheManager.Add("Report", reportList); } return reportList; } private List<AggregateModel> GenerateAreaReportData(List<AggregateModel> list, ReportType nextCommand) { List<AggregateModel> areaList = new List<AggregateModel>(); var statList = list.Where(u => Enum.GetNames(typeof(NorthArea)).Any(t => t.Equals(u.GroupKey))).ToList(); if (statList.Count > 0) { areaList.Add(new AggregateModel { GroupKey = "北台灣", Count = statList.Sum(t => t.Count), DetailList = new ArrayList(statList), NextType = ReportType.Location }); int res = statList.Sum(t => t.Count); statList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); list = list.Except((List<AggregateModel>)statList).ToList(); } statList = list.Where(u => Enum.GetNames(typeof(CenterArea)).Any(t => t.Equals(u.GroupKey))).ToList(); if (statList.Count > 0) { areaList.Add(new AggregateModel { GroupKey = "中台灣", Count = statList.Sum(t => t.Count), DetailList = new ArrayList(statList), NextType = ReportType.Location }); int res = statList.Sum(t => t.Count); statList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); list = list.Except((List<AggregateModel>)statList).ToList(); } statList = list.Where(u => Enum.GetNames(typeof(SouthArea)).Any(t => t.Equals(u.GroupKey))).ToList(); if (statList.Count > 0) { areaList.Add(new AggregateModel { GroupKey = "南台灣", Count = statList.Sum(t => t.Count), DetailList = new ArrayList(statList), NextType = ReportType.Location }); int res = statList.Sum(t => t.Count); statList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); list = list.Except((List<AggregateModel>)statList).ToList(); } statList = list.Where(u => Enum.GetNames(typeof(EastArea)).Any(t => t.Equals(u.GroupKey))).ToList(); if (statList.Count > 0) { areaList.Add(new AggregateModel { GroupKey = "東台灣", Count = statList.Sum(t => t.Count), DetailList = new ArrayList(statList), NextType = ReportType.Location }); int res = statList.Sum(t => t.Count); statList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); list = list.Except((List<AggregateModel>)statList).ToList(); } statList = list.Where(u => Enum.GetNames(typeof(OffshoreIsland)).Any(t => t.Equals(u.GroupKey))).ToList(); if (statList.Count > 0) { areaList.Add(new AggregateModel { GroupKey = "外島或離島", Count = statList.Sum(t => t.Count), DetailList = new ArrayList(statList), NextType = ReportType.Location }); int res = statList.Sum(t => t.Count); statList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); list = list.Except((List<AggregateModel>)statList).ToList(); } if (list.Count > 0) { int res = list.Sum(t => t.Count); list.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AggregateModel { GroupKey = "其他", Count = list.Sum(t => t.Count), DetailList = new ArrayList(list), NextType = ReportType.Location }); } areaList.ForEach(t => t.Percentage = (float)t.Count / (float)areaList.Sum(u => u.Count) * 100); return areaList; } private List<AggregateModel> GenerateAreaReportData(ArrayList list, ReportType nextCommand) { List<AggregateModel> areaList = new List<AggregateModel>(); var statList = list.Cast<MemberAnalysisDetailModel>().ToList().Where(u => Enum.GetNames(typeof(NorthArea)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var newList = statList.GroupBy(w => w.Location).Select(u => new AggregateModel { GroupKey = u.Key, Count = u.Sum(item => item.Count), DetailList = new ArrayList(u.ToList()), NextType = nextCommand }).ToList(); int res = newList.Sum(t => t.Count); newList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AggregateModel { GroupKey = "北台灣", Count = newList.Sum(t => t.Count), DetailList = new ArrayList(newList), NextType = ReportType.Location }); list = new ArrayList(list.Cast<MemberAnalysisDetailModel>().ToList().Except((List<MemberAnalysisDetailModel>)statList).ToList()); } statList = list.Cast<MemberAnalysisDetailModel>().ToList().Where(u => Enum.GetNames(typeof(CenterArea)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var newList = statList.GroupBy(w => w.Location).Select(u => new AggregateModel { GroupKey = u.Key, Count = u.Sum(item => item.Count), DetailList = new ArrayList(u.ToList()), NextType = nextCommand }).ToList(); int res = newList.Sum(t => t.Count); newList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AggregateModel { GroupKey = "中台灣", Count = newList.Sum(t => t.Count), DetailList = new ArrayList(newList), NextType = ReportType.Location }); list = new ArrayList(list.Cast<MemberAnalysisDetailModel>().ToList().Except((List<MemberAnalysisDetailModel>)statList).ToList()); } statList = list.Cast<MemberAnalysisDetailModel>().ToList().Where(u => Enum.GetNames(typeof(SouthArea)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var newList = statList.GroupBy(w => w.Location).Select(u => new AggregateModel { GroupKey = u.Key, Count = u.Sum(item => item.Count), DetailList = new ArrayList(u.ToList()), NextType = nextCommand }).ToList(); int res = newList.Sum(t => t.Count); newList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AggregateModel { GroupKey = "南台灣", Count = newList.Sum(t => t.Count), DetailList = new ArrayList(newList), NextType = ReportType.Location }); list = new ArrayList(list.Cast<MemberAnalysisDetailModel>().ToList().Except((List<MemberAnalysisDetailModel>)statList).ToList()); } statList = list.Cast<MemberAnalysisDetailModel>().ToList().Where(u => Enum.GetNames(typeof(EastArea)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var newList = statList.GroupBy(w => w.Location).Select(u => new AggregateModel { GroupKey = u.Key, Count = u.Sum(item => item.Count), DetailList = new ArrayList(u.ToList()), NextType = nextCommand }).ToList(); int res = newList.Sum(t => t.Count); newList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AggregateModel { GroupKey = "東台灣", Count = newList.Sum(t => t.Count), DetailList = new ArrayList(newList), NextType = ReportType.Location }); list = new ArrayList(list.Cast<MemberAnalysisDetailModel>().ToList().Except((List<MemberAnalysisDetailModel>)statList).ToList()); } statList = list.Cast<MemberAnalysisDetailModel>().ToList().Where(u => Enum.GetNames(typeof(OffshoreIsland)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var newList = statList.GroupBy(w => w.Location).Select(u => new AggregateModel { GroupKey = u.Key, Count = u.Sum(item => item.Count), DetailList = new ArrayList(u.ToList()), NextType = nextCommand }).ToList(); int res = newList.Sum(t => t.Count); newList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AggregateModel { GroupKey = "外島或離島", Count = newList.Sum(t => t.Count), DetailList = new ArrayList(newList), NextType = ReportType.Location }); list = new ArrayList(list.Cast<MemberAnalysisDetailModel>().ToList().Except((List<MemberAnalysisDetailModel>)statList).ToList()); } if (list.Count > 0) { var newList = list.Cast<MemberAnalysisDetailModel>().ToList().GroupBy(w => w.Location).Select(u => new AggregateModel { GroupKey = u.Key, Count = u.Sum(item => item.Count), DetailList = new ArrayList(u.ToList()), NextType = nextCommand }).ToList(); int res = newList.Sum(t => t.Count); newList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AggregateModel() { GroupKey = "其他", Count = list.Cast<MemberAnalysisDetailModel>().ToList().Sum(t => t.Count), DetailList = new ArrayList(newList), NextType = ReportType.Location }); } return areaList; } private List<AreaModel> GenerateAreaReportData() { var data = cacheManager.GetData("AreaReport") as List<AreaModel>; if (data != null) return data; List<AreaModel> areaList = new List<AreaModel>(); List<MemberAnalysisDetailModel> list = GetData(); var statList = list.Where(u => Enum.GetNames(typeof(NorthArea)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var countryList = statList.GroupBy(w => w.Location).Select(u => new MemberAnalysisDetailModel { Location = u.Key, Count = u.Sum(item => item.Count) }).ToList(); int res = countryList.Sum(t => t.Count); countryList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AreaModel() { Area = " 北台灣", Count = countryList.Sum(t => t.Count), CountriesList = countryList }); list = list.Except((List<MemberAnalysisDetailModel>)statList).ToList(); } statList = list.Where(u => Enum.GetNames(typeof(CenterArea)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var countryList = statList.GroupBy(w => w.Location).Select(u => new MemberAnalysisDetailModel { Location = u.Key, Count = u.Sum(item => item.Count) }).ToList(); int res = countryList.Sum(t => t.Count); countryList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AreaModel() { Area = "中台灣", Count = countryList.Sum(t => t.Count), CountriesList = countryList }); list = list.Except((List<MemberAnalysisDetailModel>)statList).ToList(); } statList = list.Where(u => Enum.GetNames(typeof(SouthArea)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var countryList = statList.GroupBy(w => w.Location).Select(u => new MemberAnalysisDetailModel { Location = u.Key, Count = u.Sum(item => item.Count) }).ToList(); int res = countryList.Sum(t => t.Count); countryList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AreaModel() { Area = "南台灣", Count = countryList.Sum(t => t.Count), CountriesList = countryList }); list = list.Except((List<MemberAnalysisDetailModel>)statList).ToList(); } statList = list.Where(u => Enum.GetNames(typeof(EastArea)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var countryList = statList.GroupBy(w => w.Location).Select(u => new MemberAnalysisDetailModel { Location = u.Key, Count = u.Sum(item => item.Count) }).ToList(); int res = countryList.Sum(t => t.Count); countryList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AreaModel() { Area = "東台灣", Count = countryList.Sum(t => t.Count), CountriesList = countryList }); list = list.Except((List<MemberAnalysisDetailModel>)statList).ToList(); } statList = list.Where(u => Enum.GetNames(typeof(OffshoreIsland)).Any(t => t.Equals(u.Location))).ToList(); if (statList.Count > 0) { var countryList = statList.GroupBy(w => w.Location).Select(u => new MemberAnalysisDetailModel { Location = u.Key, Count = u.Sum(item => item.Count) }).ToList(); int res = countryList.Sum(t => t.Count); countryList.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AreaModel() { Area = "外島或離島", Count = countryList.Sum(t => t.Count), CountriesList = countryList }); list = list.Except((List<MemberAnalysisDetailModel>)statList).ToList(); } if (list.Count > 0) { int res = list.Sum(t => t.Count); list.ForEach(t => t.Percentage = (float)t.Count / (float)res * 100); areaList.Add(new AreaModel() { Area = "其他", Count = list.Sum(t => t.Count), CountriesList = list }); areaList.ForEach(t => t.Percentage = (float)t.Count / (float)areaList.Sum(u => u.Count) * 100); } int sum = areaList.Sum(t => t.Count); areaList.ForEach(t => t.Percentage = (float)t.Count / (float)sum * 100); cacheManager.Add("AreaReport", areaList); return areaList; } private void ShowLocationReport() { QueryView.Report.Children.Clear(); QueryView.Report.Children.Add(GenerateAreaView()); QueryView.busyr.IsBusy = false; } private RadGridView GenerateAreaView() { List<AreaModel> areaList = GenerateAreaReportData(); string key = "Area"; RadGridView aggregateView = GenerateGridview(key); if (aggregateView == null) throw new Exception("Fail!!"); aggregateView.ItemTemplate = CreateDataTemplate(); aggregateView.ItemsSource = areaList; Dictionary<string, int> dictionary = areaList .GroupBy(p => p.Area, StringComparer.OrdinalIgnoreCase) .ToDictionary(g => g.Key, g => g.First().Count, StringComparer.OrdinalIgnoreCase); GeneratePieChart(dictionary); return aggregateView; } private void ShowAgeReport() { string key = "Age"; RadGridView view = GenerateGridview(key); if (view == null) throw new Exception("Fail!!"); QueryView.Report.Children.Clear(); QueryView.Report.Children.Add(view); List<MemberAnalysisDetailModel> statList = GetData(); var res = statList.GroupBy(w => w.Age).Select(u => new MemberAnalysisDetailModel { Age = u.Key, Count = u.Sum(item => item.Count) }).ToList(); int sum = res.Sum(t => t.Count); res.ForEach(t => t.Percentage = (float)t.Count / (float)sum * 100); view.ItemsSource = res.OrderBy(t=>t.Age).ToList(); Dictionary<string, int> dictionary = res.GroupBy(p => p.Age, StringComparer.OrdinalIgnoreCase).ToDictionary(g => g.Key, g => g.First().Count, StringComparer.OrdinalIgnoreCase); GeneratePieChart(dictionary); QueryView.busyr.IsBusy = false; } private void ShowGenderReport() { string key = "Gender"; RadGridView view = GenerateGridview(key); if (view == null) throw new Exception("Fail!!"); QueryView.Report.Children.Clear(); QueryView.Report.Children.Add(view); List<MemberAnalysisDetailModel> statList = GetData(); var res = statList.GroupBy(w => w.Gender).Select(u => new MemberAnalysisDetailModel { Gender = u.Key, Count = u.Sum(item => item.Count) }).ToList(); int sum = res.Sum(t => t.Count); res.ForEach(t => t.Percentage = (float)t.Count / (float)sum * 100); view.ItemsSource = res; Dictionary<string,int> dictionary = res.GroupBy(p => p.Gender, StringComparer.OrdinalIgnoreCase).ToDictionary(g => g.Key, g => g.First().Count, StringComparer.OrdinalIgnoreCase); GeneratePieChart(dictionary); QueryView.busyr.IsBusy = false; } private RadGridView GenerateGridview(string key) { GridViewDataColumn column = (GridViewDataColumn)HeaderDictionary[key]; if (column == null) return null; RadGridView view = new RadGridView() { CanUserSortGroups = false, CanUserInsertRows = false, CanUserFreezeColumns = false, CanUserDeleteRows = false, AutoGenerateColumns = false, ShowGroupPanel = false, ShowColumnFooters = true, ShowGroupFooters = true, MaxHeight = QueryView.Report.MaxHeight }; if ("area".Equals(key, StringComparison.CurrentCultureIgnoreCase)) { view.RowDetailsTemplate = CreateDataTemplate(); GridViewToggleRowDetailsColumn toggleRowColumn = new GridViewToggleRowDetailsColumn(); view.Columns.Add(toggleRowColumn); } view.Columns.Add(column); view.RowDetailsVisibilityChanged += new EventHandler<Telerik.Windows.Controls.GridView.GridViewRowDetailsEventArgs>(view_RowDetailsVisibilityChanged); view.Columns.Add((GridViewDataColumn)HeaderDictionary["Count"]); view.Columns.Add((GridViewDataColumn)HeaderDictionary["Percentage"]); return view; } void view_RowDetailsVisibilityChanged(object sender, Telerik.Windows.Controls.GridView.GridViewRowDetailsEventArgs e) { Dictionary<string, int> dictionary = (e.Visibility.Equals(Visibility.Visible))? ((AreaModel)e.Row.Item).CountriesList.GroupBy(p => p.Location, StringComparer.OrdinalIgnoreCase).ToDictionary(g => g.Key, g => g.First().Count, StringComparer.OrdinalIgnoreCase): GenerateAreaReportData().GroupBy(p => p.Area, StringComparer.OrdinalIgnoreCase).ToDictionary(g => g.Key, g => g.First().Count, StringComparer.OrdinalIgnoreCase); GeneratePieChart(dictionary); } private void GenerateHeaderDictionary() { HeaderDictionary.Add("Age", new GridViewDataColumn() { DataMemberBinding = new System.Windows.Data.Binding("Age"), Header = "年齡", IsReadOnly = true, TabStopMode = Telerik.Windows.Controls.GridView.GridViewTabStop.Skip, Width = 80, TextAlignment = System.Windows.TextAlignment.Center }); HeaderDictionary.Add("Gender", new GridViewDataColumn() { DataMemberBinding = new System.Windows.Data.Binding("Gender"), Header = "性別", IsReadOnly = true, TabStopMode = Telerik.Windows.Controls.GridView.GridViewTabStop.Skip, Width = 80, TextAlignment = System.Windows.TextAlignment.Center }); HeaderDictionary.Add("Area", new GridViewDataColumn() { DataMemberBinding = new System.Windows.Data.Binding("Area"), Header = "區域", IsReadOnly = true, TabStopMode = Telerik.Windows.Controls.GridView.GridViewTabStop.Skip, Width = 80, TextAlignment = System.Windows.TextAlignment.Center }); HeaderDictionary.Add("AgeMultiSelected", new GridViewDataColumn() { DataMemberBinding = new System.Windows.Data.Binding("GroupKey"), Header = "年齡", IsReadOnly = true, TabStopMode = Telerik.Windows.Controls.GridView.GridViewTabStop.Skip, Width = 80, TextAlignment = System.Windows.TextAlignment.Center }); HeaderDictionary.Add("LocationMultiSelected", new GridViewDataColumn() { DataMemberBinding = new System.Windows.Data.Binding("GroupKey"), Header = "區域", IsReadOnly = true, TabStopMode = Telerik.Windows.Controls.GridView.GridViewTabStop.Skip, Width = 80, TextAlignment = System.Windows.TextAlignment.Center }); HeaderDictionary.Add("GenderMultiSelected", new GridViewDataColumn() { DataMemberBinding = new System.Windows.Data.Binding("GroupKey"), Header = "性別", IsReadOnly = true, TabStopMode = Telerik.Windows.Controls.GridView.GridViewTabStop.Skip, Width = 80, TextAlignment = System.Windows.TextAlignment.Center }); GridViewDataColumn column = new GridViewDataColumn() { DataMemberBinding = new System.Windows.Data.Binding("Count"), Header = "人數", IsReadOnly = true, TabStopMode = Telerik.Windows.Controls.GridView.GridViewTabStop.Skip, DataFormatString = "{0:N0}", TextAlignment = System.Windows.TextAlignment.Right, Width = 80 }; column.AggregateFunctions.Add(new SumFunction() { Caption = "總計", FunctionName = "Count", ResultFormatString = "{0:N0}" }); HeaderDictionary.Add("Count", column); column = new GridViewDataColumn() { DataMemberBinding = new System.Windows.Data.Binding("Percentage"), Header = "百分比", IsReadOnly = true, TabStopMode = Telerik.Windows.Controls.GridView.GridViewTabStop.Skip, DataFormatString = "{0:f2}%", TextAlignment = System.Windows.TextAlignment.Right, Width = 80 }; column.AggregateFunctions.Add(new SumFunction() { SourceField = "Percentage", ResultFormatString = "{0:f2}%" }); HeaderDictionary.Add("Percentage", column); HeaderKeyDictionary.Add("Age", "年齡"); HeaderKeyDictionary.Add("Gender", "性別"); HeaderKeyDictionary.Add("Location", "區域"); } private DataTemplate CreateNewDataTemplate() { string rtnXaml = string.Empty; string baseXaml = @"<DataTemplate x:Key='RowDetailsTemplate' xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:telerik='http://schemas.telerik.com/2008/xaml/presentation' xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""> <telerik:RadGridView Name='SubListGrid{KEYTYPE}' ItemsSource='{Binding DetailList}' AutoGenerateColumns='False' CanUserSortGroups='False' CanUserInsertRows='False' CanUserFreezeColumns='False' CanUserDeleteRows='False' ShowGroupPanel='False' IsReadOnly='true'> <telerik:RadGridView.Columns> {TOGGLEROWDETAILCOLUMN} <telerik:GridViewDataColumn Header='{HEADER}' DataMemberBinding='{Binding GroupKey}' TextAlignment='Center'/> <telerik:GridViewDataColumn Header='人數' DataMemberBinding='{Binding Count}' TextAlignment='Right' DataFormatString = '{}{0:N0}'/> <telerik:GridViewDataColumn Header='百分比' DataMemberBinding='{Binding Percentage}' DataFormatString = '{}{0:f2}%' TextAlignment='Right'/> </telerik:RadGridView.Columns> {SUBTEMPLATE} </telerik:RadGridView> </DataTemplate>"; string subLevelXaml = @"<telerik:RadGridView.RowDetailsTemplate> <DataTemplate x:Key='RowDetailsTemplate'> <telerik:RadGridView Name='SubListGrid{KEYTYPE}' ItemsSource='{Binding DetailList}' AutoGenerateColumns='False' CanUserSortGroups='False' CanUserInsertRows='False' CanUserFreezeColumns='False' CanUserDeleteRows='False' ShowGroupPanel='False' IsReadOnly='true'> <telerik:RadGridView.Columns> {TOGGLEROWDETAILCOLUMN} <telerik:GridViewDataColumn Header='{HEADER}' DataMemberBinding='{Binding GroupKey}' TextAlignment='Center'/> <telerik:GridViewDataColumn Header='人數' DataMemberBinding='{Binding Count}' TextAlignment='Right' DataFormatString = '{}{0:N0}'/> <telerik:GridViewDataColumn Header='百分比' DataMemberBinding='{Binding Percentage}' DataFormatString = '{}{0:f2}%' TextAlignment='Right'/> </telerik:RadGridView.Columns> {SUBTEMPLATE} </telerik:RadGridView> </DataTemplate> </telerik:RadGridView.RowDetailsTemplate>"; foreach (ReportType type in command) { if (command.First().Equals(type)) { if (ReportType.Location.Equals(type)) rtnXaml = baseXaml.Replace("{KEYTYPE}", "Area").Replace("{HEADER}", "縣/市"); continue; } if (rtnXaml.Equals(string.Empty)) { rtnXaml = baseXaml.Replace("{KEYTYPE}", type.ToString()).Replace("{HEADER}", HeaderKeyDictionary[type.ToString()].ToString()); } else { string subXaml = subLevelXaml.Replace("{KEYTYPE}", type.ToString()).Replace("{HEADER}", HeaderKeyDictionary[type.ToString()].ToString()); rtnXaml = rtnXaml.Replace("{TOGGLEROWDETAILCOLUMN}", "<telerik:GridViewToggleRowDetailsColumn/>").Replace("{SUBTEMPLATE}", subXaml); } if (ReportType.Location.Equals(type)) { string subXaml = subLevelXaml.Replace("{KEYTYPE}", "Area").Replace("{HEADER}", "縣/市"); rtnXaml = rtnXaml.Replace("{TOGGLEROWDETAILCOLUMN}", "<telerik:GridViewToggleRowDetailsColumn/>").Replace("{SUBTEMPLATE}", subXaml); } } rtnXaml = rtnXaml.Replace("{TOGGLEROWDETAILCOLUMN}", string.Empty).Replace("{SUBTEMPLATE}", string.Empty); System.Text.UTF8Encoding myEncoder = new System.Text.UTF8Encoding(); byte[] bytes = myEncoder.GetBytes(rtnXaml); MemoryStream ms = new MemoryStream(bytes); DataTemplate dt = (DataTemplate)XamlReader.Load(ms); return dt; } private DataTemplate CreateDataTemplate() { string xaml = @"<DataTemplate x:Key='RowDetailsTemplate' xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:telerik='http://schemas.telerik.com/2008/xaml/presentation' xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""> <telerik:RadGridView Name='CountryGrid' ItemsSource='{Binding CountriesList}' AutoGenerateColumns='False' CanUserSortGroups='False' CanUserInsertRows='False' CanUserFreezeColumns='False' CanUserDeleteRows='False' ShowGroupPanel='False' IsReadOnly='true'> <telerik:RadGridView.Columns> <telerik:GridViewDataColumn Header='縣/市' DataMemberBinding='{Binding Location}' TextAlignment='Center'/> <telerik:GridViewDataColumn Header='人數' DataMemberBinding='{Binding Count}' TextAlignment='Right' DataFormatString = '{}{0:N0}'/> <telerik:GridViewDataColumn Header='百分比' DataMemberBinding='{Binding Percentage}' DataFormatString = '{}{0:f2}%' TextAlignment='Right'/> </telerik:RadGridView.Columns> </telerik:RadGridView> </DataTemplate>"; System.Text.UTF8Encoding myEncoder = new System.Text.UTF8Encoding(); byte[] bytes = myEncoder.GetBytes(xaml); MemoryStream ms = new MemoryStream(bytes); DataTemplate dt = (DataTemplate)XamlReader.Load(ms); return dt; } public override bool ExitCommandBinding_CanExecuted(object parameter) { return base.ExitCommandBinding_CanExecuted(parameter); } public override void ExitCommandBinding_Executed(object parameter) { base.ExitCommandBinding_Executed(parameter); } }}