2012-08-16 39 views
8

मुझे एक डब्ल्यूपीएफ डाटाग्रिड मिला है, और मुझे यह मिला है कि आप कॉलम हेडर पर क्लिक करके इसे सॉर्ट कर सकते हैं। यह काम करता है, लेकिन यह अस्थिर है। मैं इसे स्थिर सॉर्टिंग कैसे कर सकता हूं?स्थिर सॉर्टिंग का उपयोग कर डेटाग्रिड को कैसे सॉर्ट करें?

इस मेरा मतलब है, के द्वारा अगर मैं इस तालिका है: अब प्रकार वर्ग द्वारा

Class | Student | Grade 
----------------------------- 
Art  | Amy  | B 
Science | Amy  | A 
History | Amy  | A 
Art  | Charlie | A 
Science | Charlie | C 
History | Charlie | C 
Art  | James  | A 
Science | James  | D 
History | James  | B 

लेकिन अगर मैं:

Class | Student | Grade 
----------------------------- 
Art  | James  | A 
Art  | Amy  | B 
Art  | Charlie | A 
Science | James  | D 
Science | Amy  | A 
Science | Charlie | C 
History | James  | B 
History | Amy  | A 
History | Charlie | C 

मैं इन सबसे छात्र द्वारा करते हैं, तो यह काम करता है जैसे आप उम्मीद थी :

Class | Student | Grade 
----------------------------- 
Art  | James  | A 
Art  | Amy  | B 
Art  | Charlie | A 
History | James  | B 
History | Amy  | A 
History | Charlie | C 
Science | James  | D 
Science | Amy  | A 
Science | Charlie | C 

यह छात्रों के क्रम क्रम को नष्ट कर दिया गया है (अस्थिर सॉर्टिंग)।

Class | Student | Grade 
----------------------------- 
Art  | Amy  | B 
Art  | Charlie | A 
Art  | James  | A 
History | Amy  | A 
History | Charlie | C 
History | James  | B 
Science | Amy  | A 
Science | Charlie | C 
Science | James  | D 

लगता है जैसे कि यह डिफ़ॉल्ट रूप से इस तरह काम करना चाहिए, या कम से कम एक टॉगल हो: क्या मैं चाहता हूँ स्थिर छंटाई, जहां यह आदेश को बरकरार रखता है है। क्या किसी के पास कोई सुझाव है? @ ईरिक के शिफ्ट-क्लिक कार्यों का विचार, और इससे पता चलता है कि व्यवहार मौजूद है। हालांकि, मुझे वास्तव में क्या पसंद आएगा बिना किसी संशोधक के काम करना। यह "इसके द्वारा क्रमबद्ध करने का कारण नहीं होना चाहिए, फिर यह, फिर यह", यह एक अलग के लिए एल्गोरिदम स्वैप करने का मामला होना चाहिए। http://en.wikipedia.org/wiki/Sorting_algorithm#Stability

+0

क्या आप इसे पीछे कोड में करने का कोई तरीका ढूंढ रहे हैं, या उम्मीद कर रहे हैं कि कोई शिफ्ट-क्लिक-व्यवहार को डिफ़ॉल्ट व्यवहार करने का तरीका जानेंगे? – Grubsnik

+0

@Grubsnik मैं उम्मीद कर रहा था कि कोई व्यक्ति एल्गोरिदम को कैसे बदला जाए, क्योंकि मुझे लगता है कि शिफ्ट-क्लिक दृष्टिकोण एक प्रमुख हैक है। हालांकि, यह नौकरी करता है। – TarkaDaal

उत्तर

1

मैं एक कस्टम comparer का उपयोग कर एक स्थिर छंटाई पाने के लिए प्रबंधित किया है, लेकिन यह थोड़े एक बड़ा हैक की तरह लगता है ...

मैं ListCollectionView के CustomSort संपत्ति का उपयोग जो मुझे जरूरत है पारित करने के लिए अपने कस्टम comparer, स्थापित करने के लिए इसे तत्काल करने पर इसे संग्रहित करें।

private void Sorting(IEnumerable collection) 
{ 
    var view = CollectionViewSource.GetDefaultView(collection) as ListCollectionView; 

    if (view != null) 
    { 
     view.CustomSort = new StableComparer(collection); 
    } 
} 

अपने कस्टम comparer में, मैं तुलना विधि के दौरान संग्रह का उपयोग सिर्फ आइटम अनुक्रमित पर वापस आने की जब नियमित रूप से तुलना एक शून्य (वे ही कर रहे हैं या एक ही मूल्य है) देता है।

public class StableComparer : IComparer 
{ 
    public IEnumerable Collection { get; set; } 

    public StableComparer(IEnumerable collection) 
    { 
     Collection = collection; 
    } 

    public int Compare(object x, object y) 
    { 
     IComparable x_Comparable = x as IComparable; 
     IComparable y_Comparable = y as IComparable; 

     if (x_Comparable != null && y_Comparable != null) 
     { 
      var comparison = x_Comparable.CompareTo(y_Comparable); 

      // A zero value means x and y are equivalent for sorting, and they could 
      // be rearranged by an unstable sorting algorithm 
      if (comparison == 0 && Collection != null) 
      { 
       // IndexOf is an extension method for IEnumerable (not included) 
       var x_Index = Collection.IndexOf(x); 
       var y_Index = Collection.IndexOf(y); 

       // By comparing their indexes in the original collection, we get to 
       // preserve their relative order 
       if (x_Index != -1 && y_Index != -1) 
        comparison = x_Index.CompareTo(y_Index); 
      } 

      return comparison; 
     } 

     return 0; 
    } 
} 

मैं अभी भी इस परीक्षण कर रहा हूँ, तो मैं गारंटी नहीं दे सकते यह सब समय काम करेगा ... एक समस्या यह है उदाहरण के लिए, संग्रह संपत्ति comparer अद्यतन अंदर रखने की जाएगी। या दो तरह के दिशानिर्देशों का समर्थन करना (अब इस पर काम करना मुश्किल नहीं होना चाहिए)। या यह जांचता है कि यह कैसे काम करता है, प्रदर्शन के अनुसार।

लेकिन मुझे लगता है कि विचार स्पष्ट है; हालांकि हैकी, जैसा मैंने कहा था।

8

आप एक से अधिक कॉलम से सॉर्ट करने में सक्षम होना चाहिए नीचे शिफ्ट पकड़े जब कॉलम पर क्लिक करके:

इस देखें। कक्षा कॉलम पर क्लिक करने का प्रयास करें, फिर शिफ्ट दबाएं और छात्र कॉलम पर क्लिक करें। आप मानक छंटाई निष्क्रिय करने के लिए है इस काम के लिए

private void myDataGridPreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    DependencyObject dep = (DependencyObject)e.OriginalSource; 

    while ((dep != null) && !(dep is DataGridColumnHeader)) 
    { 
     dep = VisualTreeHelper.GetParent(dep); 
    } 

    if (dep == null) 
     return; 

    if (dep is DataGridColumnHeader) 
    { 
     DataGridColumnHeader columnHeader = dep as DataGridColumnHeader; 

     ICollectionView view = CollectionViewSource.GetDefaultView((sender as DataGrid).ItemsSource); 

     if (columnHeader.Content.Equals("Class") || columnHeader.Content.Equals("Student")) 
     { 
      view.SortDescriptions.Clear(); 
      view.SortDescriptions.Add(new SortDescription("Class", ListSortDirection.Ascending)); 
      view.SortDescriptions.Add(new SortDescription("Student", ListSortDirection.Ascending)); 
     } 
    } 
} 

:

यहाँ के पीछे कोड में छँटाई जोड़ने के लिए एक समाधान है। एक तरह से यह करने के लिए तो जैसे छंटाई घटना को रोकने के लिए, यह है:

private void myDataGridSorting(object sender, DataGridSortingEventArgs e) 
{ 
    e.Handled = true; 
} 

संपादित: hbarck की टिप्पणी को पढ़ने के बाद मैं आपके सवाल का फिर से पढ़ें, और यह मैं कुछ भागों याद किया लगता है।

if (columnHeader.Content.Equals("Class") || columnHeader.Content.Equals("Student")) 
{ 
    view.SortDescriptions.Clear(); 
    view.SortDescriptions.Add(new SortDescription("Class", ListSortDirection.Ascending)); 
    view.SortDescriptions.Add(new SortDescription("Student", ListSortDirection.Ascending)); 
} 
इस के लिए

:: यदि आप इस कोड को बदलते हैं

if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) 
{ 
    view.SortDescriptions.Clear(); 
} 

view.SortDescriptions.Insert(0, new SortDescription(columnHeader.Content.ToString(), ListSortDirection.Ascending)); 

आप स्थिर छंटाई करना होगा। छात्र द्वारा क्रमबद्ध करने के लिए छात्र पर क्लिक करें, फिर वर्ग, छात्र द्वारा क्रमबद्ध करने के लिए कक्षा पर क्लिक करें। यदि आप क्लिक किए गए कॉलम से सॉर्ट करने से पहले पिछले सॉर्टिंग को साफ़ करते समय क्लिक करते समय ctrl दबाए रखें।

+0

+1। यह बहुत अच्छा है, धन्यवाद! यह अल्प अवधि में आसान है। हालांकि, मैं इसे अभी तक जवाब के रूप में चिह्नित नहीं करना चाहता हूं। आदर्श रूप से, मैं डिफ़ॉल्ट रूप से इस व्यवहार को पसंद करूंगा (इसलिए, शिफ्ट धारण किए बिना)। मैं सवाल स्पष्ट कर दूंगा। – TarkaDaal

+1

@ टार्काडाल आप फिर पिछले सॉर्टिंग को "हटाएं" कैसे करेंगे? मान लें कि आप कक्षा और छात्र द्वारा क्रमबद्ध करना चाहते हैं, लेकिन फिर आप कक्षा और ग्रेड द्वारा क्रमबद्ध करना चाहते हैं। आपको पहले क्रमबद्ध करने के लिए एक नया कॉलम सेट करने का कुछ तरीका लागू करना होगा, उदाहरण के लिए क्लिक करते समय Shift दबाएं ...;) – Eirik

+0

आपको इसकी आवश्यकता नहीं है। यदि आप कक्षा द्वारा क्रमबद्ध करना चाहते हैं, तो ग्रेड, बस कक्षा, फिर ग्रेड पर क्लिक करें। छात्र का आदेश कोई फर्क नहीं पड़ता। यह एकाधिक कॉलम द्वारा क्रमबद्ध करने के बारे में नहीं है, यह संभव है कि पिछले आदेश को संरक्षित करने के बारे में है। – TarkaDaal

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