2012-05-25 9 views
5

मैं कुछ डेटा गतिशील रूप से पुन: संरचना करने के लिए कोशिश कर रहा हूँ एक treeview होगा उपयोगकर्ता द्वारा समूह के लिए निम्न आयाम डेटा के तीन अप करने के लिए चुनने की अनुमति देता है, जिसमें दिखाया जा सकता है:बनाएं GroupBy वक्तव्य गतिशील रूप

Organisation 
Company 
Site 
Division 
Department 

तो उदाहरण के लिए, यदि उपयोगकर्ता का चयन करना था कि वे कंपनी द्वारा समूह करना चाहते हैं तो साइट तो डिवीजन ... निम्नलिखित कोड आवश्यक समूह निष्पादित करेगा।

var entities = orgEntities 
// Grouping Level 1 
.GroupBy(o => new { o.CompanyID, o.CompanyName }) 
.Select(grp1 => new TreeViewItem 
     { 
     CompanyID = grp1.Key.CompanyID, 
     DisplayName = grp1.Key.CompanyName, 
     ItemTypeEnum = TreeViewItemType.Company, 
     SubItems = grp1 
       // Grouping Level 2 
       .GroupBy(o => new { o.SiteID, o.SiteName }) 
       .Select(grp2 => new TreeViewItem 
       { 
       SiteID = grp2.Key.SiteID, 
       DisplayName = grp2.Key.SiteName, 
       ItemTypeEnum = TreeViewItemType.Site, 
       SubItems = grp2 
        // Grouping Level 3 
        .GroupBy(o => new { o.Division }) 
        .Select(grp3 => new TreeViewItem 
        { 
         DisplayName = grp3.Key.Division, 
         ItemTypeEnum = TreeViewItemType.Division, 
        }).ToList() 
       }).ToList() 
     }) 
.ToList(); 

यह इस तरह एक structre देना होगा:

+ Company A 
    + Site A 
    + Division 1 
    + Division 2 
    + Site B 
    + Division 1 
+ Company B 
    + Site C 
    + Division 2 
+ Company C 
    + Site D 

बहरहाल, यह सिर्फ मेरे संयोजनों की एक बड़ी संख्या के साथ प्रदान करता है।

मैं इसे किसी ऐसे रूप में परिवर्तित करने के बारे में कैसे जाउंगा जो उपयोगकर्ता द्वारा चुने गए तीन आयामों के आधार पर गतिशील रूप से समान अभिव्यक्ति बना सकता है और इसलिए मुझे प्रत्येक संयोजन के लिए इनमें से प्रत्येक अभिव्यक्ति को बनाने की आवश्यकता नहीं है !! ?

धन्यवाद दोस्तों।

उत्तर

4

एक दिलचस्प समस्या है। ग्रुपिंग कुंजियों और परिणामों के लिए एक और प्रकार के लिए एक ही प्रकार का चयन करना ... जो आप पूछ रहे हैं उसे प्राप्त करना बहुत संभव है।

public struct EntityGroupKey 
{ 
    public int ID {get;set;} 
    public string Name {get;set;} 
} 

public class EntityGrouper 
{ 
    public Func<Entity, EntityGroupKey> KeySelector {get;set;} 
    public Func<EntityGroupKey, TreeViewItem> ResultSelector {get;set;} 
    public EntityGrouper NextGrouping {get;set;} //null indicates leaf level 

    public List<TreeViewItem> GetItems(IEnumerable<Entity> source) 
    { 
    var query = 
     from x in source 
     group x by KeySelector(x) into g 
     let subItems = NextGrouping == null ? 
     new List<TreeViewItem>() : 
     NextGrouping.GetItems(g) 
     select new { Item = ResultSelector(g.Key), SubItems = subItems }; 

    List<TreeViewItem> result = new List<TreeViewItem>(); 
    foreach(var queryResult in query) 
    { 
      // wire up the subitems 
     queryResult.Item.SubItems = queryResult.SubItems 
     result.Add(queryResult.Item); 
    } 
    return result; 
    } 

} 

इस तरह से उपयोग किया:

EntityGrouper companyGrouper = new EntityGrouper() 
{ 
    KeySelector = o => new EntityGroupKey() {ID = o.CompanyID, Name = o.CompanyName}, 
    ResultSelector = key => new TreeViewItem 
    { 
    CompanyID = key.ID, 
    DisplayName = key.Name, 
    ItemTypeEnum = TreeViewItemType.Company 
    } 
} 

EntityGrouper divisionGrouper = new EntityGrouper() 
{ 
    KeySelector = o => new EntityGroupKey() {ID = 0, Name = o.Division}, 
    ResultSelector = key => new TreeViewItem 
    { 
    DisplayName = key.Name, 
    ItemTypeEnum = TreeViewItemType.Division 
    } 
} 

companyGrouper.NextGrouping = divisionGrouper; 

List<TreeViewItem> oneWay = companyGrouper.GetItems(source); 

companyGrouper.NextGrouping = null; 
divisionGrouper.NextGrouping = companyGrouper; 

List<TreeViewItem> otherWay = divisionGrouper.GetItems(source); 
+0

एक और तरीका 5 ग्रूपर वर्ग (प्रत्येक समूह के लिए एक समूह) को एक सामान्य इंटरफ़ेस IGroupEntities {List GetItems (IEnumerable )} के साथ बनाना है ताकि वे एक-दूसरे को कॉल कर सकें। –

+0

इस उत्तर के लिए धन्यवाद! मैंने कुछ ऐसा करने की कोशिश की थी लेकिन एक लापता लिंक होना चाहिए क्योंकि मुझे पूरा होने के लिए यह पुनरावृत्ति कभी नहीं मिला। मैंने आपके नमूने को स्टार्टर के रूप में उपयोग किया है और एक समाधान को कोड किया है जो मैं जो करने की कोशिश कर रहा था उसके लिए पूरी तरह से काम करता है। आपका बहुत बहुत धन्यवाद!!! – Penfold

+0

+100 अगर मैं कर सकता था! बहुत बढ़िया जवाब! –

0

एक अन्य विकल्प DynamicLinq उपयोग करने के लिए है। इस सीधे LINQ (जैसे LINQ2SQL के रूप में कुछ डीबी संदर्भ के माध्यम से नहीं) है, तो यह अपने ग्रुपिंग/चयनकर्ता तार रचना करके किया जा सकता:

var entities = orgEntities 
    .GroupBy("new(CompanyID, CompanyName)", "it", null) // DynamicLinq uses 'it' to reference the instance variable in lambdas. 
    .Select(grp1 => new TreeViewItem 
    { 
     ... 
     .GroupBy("new(SiteID, o.SiteName)", "it", null) 
     // And so on... 

आप कर सकते हैं शायद मापदंड प्रकार से प्रत्येक में इस सार। एकमात्र मुद्दा जो मैं देखता हूं वह है कि आंतरिक समूह एक साथ संकलन करना सबसे आसान नहीं हो सकता है, लेकिन कम से कम यह आपको कुछ दिशा में शुरू कर सकता है। डायनेमिकलिंक आपको गतिशील प्रकार बनाने की अनुमति देता है, इसलिए यह निश्चित रूप से इसे और भी सारण करना संभव है। आखिरकार, सबसे बड़ी चुनौती यह है कि आप जो समूहबद्ध कर रहे हैं उसके आधार पर, जेनरेट ट्री व्यूइटम में अलग-अलग जानकारी होती है। गतिशील LINQ के लिए अच्छा उपयोग केस, लेकिन एकमात्र समस्या जो मैं देखता हूं वह लाइन (आंतरिक समूह में) को और भी नीचे सारणीबद्ध करती है।

हमें बताएं कि आप किस चीज के साथ आते हैं, निश्चित रूप से एक दिलचस्प विचार जिसे मैंने पहले नहीं माना था।

संबंधित मुद्दे