2011-01-10 16 views
8

मैंने कई कॉलम पर डेटाग्रिड व्यू को सॉर्ट करने का एक उदाहरण खोजा है, लेकिन ऐसा लगता है कि मैं ऐसा नहीं कर सकता जो मुझे पसंद आए।एकाधिक कॉलम पर DataGridView सॉर्ट करें?

असल में, मेरे पास एक बाध्य डेटाग्रिड व्यू नियंत्रण (डेटाटेबल/डेटा व्यू के लिए बाध्य) है, और बाध्य डेटाटेबल में दो कॉलम हैं: - प्राथमिकता और दिनांक। मैं तिथि के अनुसार प्राथमिकता के भीतर क्रमबद्ध करना चाहता हूँ। यही है, प्राथमिकता कॉलम सटीकता लेता है, फिर इसकी तारीख लेकिन दोनों आरोही या अवरोही हो सकती हैं।

तो, उदाहरण के लिए, मैं कम प्राथमिकता, प्रारंभिक तिथि पहले (प्राथमिकता एएससी द्वारा आदेश, तारीख एएससी) हो सकता है, और, तिथि स्तंभ शीर्ष लेख, कम प्राथमिकता करने के लिए स्विच, देर से तारीख पहले (आदेश पर क्लिक करके प्राथमिकता से, तारीख desc)। यदि मैं प्राथमिकता पर क्लिक करता हूं, तो मैं पहले उच्च प्राथमिकता लेना चाहता हूं, फिर देर से तिथि (दिनांक कॉलम के लिए वर्तमान क्रम क्रम - प्राथमिकता desc, दिनांक desc) द्वारा क्रमबद्ध करें, लेकिन फिर दिनांक कॉलम पर क्लिक करने में सक्षम हो उच्च प्राथमिकता पर स्विच करने के लिए हेडर, प्रारंभिक दिनांक (प्राथमिकता से आदेश, दिनांक आरोही)

आदर्श रूप से, मैं आरोही या अवरोही दिखाने के लिए दोनों कॉलम पर ग्लाइफ सॉर्ट करना चाहता हूं।

किसी भी विचार या पॉइंटर्स को आभारी रूप से प्राप्त किया जाएगा।

यह (नीचे देखें) बहुत करीब लगता है, लेकिन ग्लिफ सही काम नहीं कर रहे हैं।

using System; 
using System.Windows.Forms; 

namespace WindowsFormsApplication4 
{ 
    public partial class Form1 : Form 
    { 
    DataSet1 dataset; 

    public Form1() 
    { 
     InitializeComponent(); 

     dataset = new DataSet1(); // two columns: Priority(Int32) and date (DateTime) 
     dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("01-jan-10")); 
     dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("02-jan-10")); 
     dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("03-jan-10")); 
     dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("04-jan-10")); 
     dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("05-jan-10")); 
     dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("06-jan-10")); 
     dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("07-jan-10")); 
     dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("08-jan-10")); 
     dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("09-jan-10")); 

     dataGridView1.DataSource = dataset.DataTable1.DefaultView; 

     dataGridView1.AllowUserToAddRows = false; 

     dataGridView1.Columns[0].SortMode = DataGridViewColumnSortMode.Programmatic; 
     dataGridView1.Columns[1].SortMode = DataGridViewColumnSortMode.Programmatic; 

     dataGridView1.Columns[0].HeaderCell.SortGlyphDirection = SortOrder.Ascending; 
     dataGridView1.Columns[1].HeaderCell.SortGlyphDirection = SortOrder.Ascending; 
    } 

    private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     DataGridViewColumn[] column = new[] { dataGridView1.Columns[0], dataGridView1.Columns[1] }; 

     DataGridViewColumnHeaderCell headerCell = dataGridView1.Columns[e.ColumnIndex].HeaderCell; 

     if (headerCell.SortGlyphDirection != SortOrder.Ascending) 
      headerCell.SortGlyphDirection = SortOrder.Ascending; 
     else 
      headerCell.SortGlyphDirection = SortOrder.Descending; 

     String sort = column[0].DataPropertyName + " " + fnSortDirection(column[0]) 
        + ", " 
        + column[1].DataPropertyName + " " + fnSortDirection(column[1]); 
     dataset.DataTable1.DefaultView.Sort = sort; 
     this.textBox1.Text = sort; 
    } 

    private String fnSortDirection(DataGridViewColumn column) 
    { 
     return column.HeaderCell.SortGlyphDirection != SortOrder.Descending ? "asc" : "desc"; 
    } 
    } 
} 
+0

तीर ग्लाइफ के संबंध में "सही काम नहीं कर रहे" का क्या मतलब है? मैं वास्तव में सॉर्टिंग कोड लिखने के लिए समय नहीं लेना चाहता था, लेकिन मुझे यह ठीक पहले देखने के लिए मिला है, और ऐसा लगता है कि अब आप सबसे अधिक रास्ते में हैं। –

+0

खैर ... पहले कॉलम (प्राथमिकता) के लिए ग्लिफ ऊपर और नीचे के बीच टॉगल करता है, लेकिन दूसरे कॉलम के लिए ग्लिफ किसी प्रकार का तीन-राज्य लगता है, और कुछ भी नहीं, कुछ भी नहीं दिखाता है। मुझे लगता है कि डीजीवी वास्तव में एक ही समय में दो सॉर्टिंग ग्लाइफ नहीं लेना चाहता है? मैंने "सामान्य" सॉर्टिंग के साथ एक तीसरा कॉलम जोड़ा है, और यह ठीक लगता है लेकिन (पहले दो स्तंभों पर ग्लाइफ गायब होने के साथ), लेकिन दूसरे कॉलम के लिए हेडर पर क्लिक करके मुझे पहले कॉलम पर आरोही ग्लाइफ देता है। 'मल्टीसोर्टडाटा ग्रिड व्यू' आईआईआरसी के लिए –

+0

Google। – leppie

उत्तर

3

ठीक है।

उपरोक्त कोड़ी के सुझावों के बाद, अब मेरे पास ऐसा कुछ है जो अपेक्षा के अनुसार काम करता है। मैंने हेडरसेल को उप-वर्गीकृत किया है और पेंट विधि पर अधिक सवार है (लेकिन बेस से पहले सॉर्टग्लिफ़ाइडरेशन को तुरंत सेट करके धोखा दिया गया है। पेंट) और डीजीवी अब कई सॉर्टिंग ग्लाइफ पेंट करता है।

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Windows.Forms; 

namespace WindowsFormsApplication4 
{ 
    public partial class Form1 : Form 
    { 
    DataSet1 dataset; 

    public Form1() 
    { 
     InitializeComponent(); 

     dataset = new DataSet1(); // three columns: Priority(Int32), Date (DateTime) and Description(String) 
     dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("01-jan-10"), "this"); 
     dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("02-jan-10"), "is"); 
     dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("03-jan-10"), "a"); 
     dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("04-jan-10"), "sample"); 
     dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("05-jan-10"), "of"); 
     dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("06-jan-10"), "the"); 
     dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("07-jan-10"), "data"); 
     dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("08-jan-10"), "in"); 
     dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("09-jan-10"), "use"); 

     dataGridView1.DataSource = dataset.DataTable1.DefaultView; 

     dataGridView1.AllowUserToAddRows = false; 

     dataGridView1.Columns[0].HeaderCell = new MyDataGridViewColumnHeaderCell(); 
     dataGridView1.Columns[1].HeaderCell = new MyDataGridViewColumnHeaderCell(); 

     dataGridView1.Columns[0].SortMode = DataGridViewColumnSortMode.Programmatic; 
     dataGridView1.Columns[1].SortMode = DataGridViewColumnSortMode.Programmatic; 
    } 

    private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     DataGridViewColumn clickedColumn = dataGridView1.Columns[e.ColumnIndex]; 

     if (clickedColumn.HeaderCell is MyDataGridViewColumnHeaderCell) 
     { 
      DoMultiColumnSort(); 
     } 
     else 
     { 
      dataGridView1.Columns.OfType<DataGridViewColumn>() 
           .Where(column => column.HeaderCell is MyDataGridViewColumnHeaderCell) 
           .ForEach(column => ((MyDataGridViewColumnHeaderCell)column.HeaderCell).SortOrderDirection = SortOrder.None); 
     } 

     this.textBox1.Text = dataset.DataTable1.DefaultView.Sort; 
    } 

    private void DoMultiColumnSort() 
    { 
     var sortClauses = dataGridView1.Columns.OfType<DataGridViewColumn>() 
               .Where(column => column.HeaderCell is MyDataGridViewColumnHeaderCell) 
               .Select(column => GetSortClause(column)); 

     dataset.DataTable1.DefaultView.Sort = String.Join(",", sortClauses); 
    } 

    private String GetSortClause(DataGridViewColumn column) 
    { 
     SortOrder direction = column.HeaderCell.SortGlyphDirection; 

     if (column.HeaderCell is MyDataGridViewColumnHeaderCell) 
     { 
      direction = ((MyDataGridViewColumnHeaderCell)column.HeaderCell).SortOrderDirection; 
     } 

     return column.DataPropertyName + " " + (direction == SortOrder.Descending ? "DESC" : "ASC"); 
    } 
    } 

    public partial class MyDataGridViewColumnHeaderCell : DataGridViewColumnHeaderCell 
    { 
    public SortOrder SortOrderDirection { get; set; } // defaults to zero = SortOrder.None; 

    protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates dataGridViewElementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) 
    { 
     this.SortGlyphDirection = this.SortOrderDirection; 
     base.Paint(graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); 
    } 

    public override object Clone() 
    { 
     MyDataGridViewColumnHeaderCell result = (MyDataGridViewColumnHeaderCell)base.Clone(); 
     result.SortOrderDirection = this.SortOrderDirection; 
     return result; 
    } 

    protected override void OnClick(DataGridViewCellEventArgs e) 
    { 
     this.SortOrderDirection = (this.SortOrderDirection != SortOrder.Ascending) ? SortOrder.Ascending : SortOrder.Descending; 
     base.OnClick(e); 
    } 
    } 

    public static partial class Extensions 
    { 
    public static void ForEach<T>(this IEnumerable<T> value, Action<T> action) { foreach (T item in value) { action(item); } } 
    } 
} 
+0

मैंने सिर्फ मजेदार के लिए लिंक सामग्री में फेंक दिया, लेकिन मुझे विश्वास नहीं है कि यह एक अच्छा दृष्टिकोण है (विशेष रूप से "फॉरएच" एक्सटेंशन)। विचार? –

7

पहली बार मैं इस पढ़ा है, मैं पूरी तरह छँटाई के बारे में हिस्सा कई द्वारा स्तंभों को एक साथ याद किया (मेरी गलती है, आपकी नहीं, सवाल पूरी तरह से स्पष्ट हो गया था)।

यदि ऐसा है, तो आपको वह कोड लिखना होगा जो इसे स्वयं संभालता है। प्रदत्त DataGridView नियंत्रण डिफ़ॉल्ट रूप से बहु-कॉलम सॉर्टिंग का समर्थन नहीं करता है। सौभाग्य से, दूसरों ने आपके लिए इसे लागू करने के लिए पहले ही बहुत सारे काम किए हैं। यहाँ कुछ नमूने हैं: यदि आप किसी डेटा स्रोत के लिए अपने DataGridView बाँध,

वैकल्पिक रूप से

  • DataGridView Multi-column Sort (CodeProject)
  • How To Allow To Sort By Multiple Columns in Custom Data Binding (CodeProject), उस डेटा स्रोत एकाधिक स्तंभों पर क्रमबद्ध किया जा सके और DataGridView नियंत्रण उस सॉर्टिंग का सम्मान करेगा। कोई भी डेटा स्रोत जो IBindingListView लागू करता है और Sort संपत्ति का खुलासा करता है, बहु-कॉलम सॉर्टिंग के लिए काम करेगा।


    हालांकि, मार्ग है कि आप बहु-स्तंभ सॉर्टिंग सक्षम करने का निर्णय की परवाह किए बिना, आप नहीं DataGridView coercing एकाधिक स्तंभों पर तरह तीर ग्लिफ़ प्रदर्शित करने के लिए ज्यादा सफलता के लिए जा रहे हैं। यहां सबसे आसान समाधान है कि आप अपने स्वयं के सॉर्ट ग्लाइफ प्रदान करने के लिए केवल कॉलम हेडर को आकर्षित करें।

    ऐसा करने के लिए, DataGridView.CellPainting event पर एक हैंडलर संलग्न करें और --1 (कॉलम हेडर इंगित करना) की जांच करें। मालिक द्वारा खींचे गए कॉलम हेडर here का पूरा नमूना है। मैं दृढ़ता से पारंपरिक तीर आइकन के साथ चिपकने की सलाह देता हूं, लेकिन एक बार जब आप इस मार्ग पर जाते हैं, तो विकल्प वास्तव में असीमित होते हैं।आप अपने कॉलम हेडर को अपनी इच्छानुसार कुछ भी दिख सकते हैं, और अलग-अलग आइकन का उपयोग करके सॉर्ट ऑर्डर में प्रत्येक कॉलम के सापेक्ष वजन को भी इंगित कर सकते हैं।

    आप DataGridViewColumnHeaderCell से एक नई कक्षा प्राप्त करने का चयन भी कर सकते हैं और Paint method ओवरराइड कर सकते हैं। यह शायद एक ही चीज़ को पूरा करने का एक क्लीनर, अधिक ऑब्जेक्ट उन्मुख तरीका है।

+0

कोडी, समाधान का सुझाव देने के लिए समय निकालने के लिए बहुत धन्यवाद - इसकी बहुत सराहना की जाती है। मैं हेडरसेल/ऑनपेंट विधि के साथ गया, लेकिन आपके अन्य सुझावों की भी जांच कर सकता हूं। –

4

DataGridView सभी मामलों में यह DataView को refere में डेटास्रोत (DataView, BindingSource, टेबल, डेटासेट + 'tablename ") को बांधता है। इस DataView का संदर्भ लें और सेट क्रमबद्ध (और फ़िल्टर) के रूप में आप चाहते हैं:

DataView dv = null; 
CurrencyManager cm = (CurrencyManager)(dgv.BindingContext[dgv.DataSource, dgv.DataMember]); 

if (cm.List is BindingSource) 
{ 
    // In case of BindingSource it may be chain of BindingSources+relations 
    BindingSource bs = (BindingSource)cm.List; 
    while (bs.List is BindingSource) 
    { bs = bs.List as BindingSource; } 

    if (bs.List is DataView) 
    { dv = bs.List as DataView; } 
} 
else if (cm.List is DataView) 
{ 
    // dgv bind to the DataView, Table or DataSet+"tablename" 
    dv = cm.List as DataView; 
} 

if (dv != null) 
{ 
    dv.Sort = "somedate desc, firstname"; 
    // dv.Filter = "lastname = 'Smith' OR lastname = 'Doe'"; 

    // You can Set the Glyphs something like this: 
    int somedateColIdx = 5; // somedate 
    int firstnameColIdx = 3; // firstname 
    dgv.Columns[somedateColIdx].HeaderCell.SortGlyphDirection = SortOrder.Descending; 
    dgv.Columns[firstnameColIdx].HeaderCell.SortGlyphDirection = SortOrder.Ascending; 
} 

नोट: स्तंभ क्रमबद्ध और फ़िल्टर में उपयोग होने वाले नाम DataTable में स्तंभ नाम के अनुरूप, में कॉलम नाम DataGridView अंतर्निहित डेटा प्रॉपर्टी नाम हैं जो बाइंडिंग के लिए उपयोग किए जाते हैं (कक्षाओं के लिए संपत्ति नाम, डेटाटेबल्स के लिए कॉलम नाम इत्यादि)।

string colName = dgv.Columns[colIdx].DataPropertyName 

कैसे आप हल कर स्तंभों ट्रैक करना चाहते हैं की निर्भर करता है (colSequence, colName, एएससी/desc, dgvColIdx) आप क्रमबद्ध का निर्माण और अभिव्यक्ति फिल्टर करने के लिए कैसे तय कर सकते हैं और: आप स्तंभ इस तरह DataView में प्रयोग किया जाता नाम प्राप्त कर सकते हैं डीजीवी में सॉर्टग्लिफ सेट करें (मैंने सादगी के लिए हार्डकोड बनाया है)।

2

मैंने कभी यहां एक प्रश्न का उत्तर नहीं दिया है, इसलिए प्रारूप गलत होने पर मैं क्षमा चाहता हूं, लेकिन मुझे इस प्रश्न का उत्तर मिला जो भविष्य के आगंतुकों के लिए आसान हो सकता है। (http://www.pcreview.co.uk/threads/datagridview-glyphs.3145090/ देखें)

Dim dictionarySortColumns As New Dictionary(Of String, Integer) 


Private Sub DataGridViewFileLoader_Sorted(sender As Object, e As EventArgs) Handles DataGridViewFileLoader.Sorted 


    Dim dv As New DataView(dataSetLoadScreener.Tables(0)) 
    Dim columnHeader As String = DataGridViewFileLoader.SortedColumn.Name 

    Dim sortDirection As Integer = DataGridViewFileLoader.SortOrder 
    Dim sortcode As String = "" 
    Dim sortOrder As String = "" 

    If sortDirection = 1 Then 
     sortOrder = "ASC" 
    Else 
     sortOrder = "DESC" 
    End If 

    If dictionarySortColumns.ContainsKey(columnHeader) Then 
     dictionarySortColumns.Remove(columnHeader) 
    End If 

    sortcode = columnHeader + " " + sortOrder 

    For Each colHeader As String In dictionarySortColumns.Keys 
     If dictionarySortColumns(colHeader) = 1 Then 
      sortOrder = "ASC" 
     Else 
      sortOrder = "DESC" 
     End If 

     sortcode = sortcode + "," + colHeader + " " + sortOrder 

    Next 

    dictionarySortColumns.Add(columnHeader, sortDirection) 

    dv.Sort = sortcode 
    DataGridViewFileLoader.DataSource = Nothing 
    DataGridViewFileLoader.DataSource = dv 

    formatDataGridViewFileLoader() 

End Sub 

Private Sub DataGridViewFileLoader_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridViewFileLoader.CellPainting 
    Dim sOrder As System.Windows.Forms.SortOrder 

    For Each key As String In dictionarySortColumns.Keys 
     If dictionarySortColumns(key) = 1 Then 
      sOrder = Windows.Forms.SortOrder.Ascending 
     Else 
      sOrder = Windows.Forms.SortOrder.Descending 
     End If 

     DataGridViewFileLoader.Columns(key).HeaderCell.SortGlyphDirection = sOrder 
    Next 
End Sub 
+0

क्या आप कृपया बता सकते हैं कि इससे ब्लैक लाइट को उनके मुद्दे के साथ क्यों मदद मिलेगी? –

+1

अच्छी तरह से, मुझे ब्लैक लाइट का सवाल यह समझा जाता है कि वे डेटाव्यू के लिए बाध्य कॉलम पर प्राथमिक और द्वितीयक सॉर्टिंग करना चाहते हैं, और उसके बाद प्रत्येक शीर्षलेख पर ग्लिफ होना चाहिए जो कहता है कि यह किस दिशा में सॉर्ट कर रहा है।यह कोड प्राथमिकता देता है कि स्तंभों को क्रमबद्ध किया गया है, सबसे हालिया कॉलम को सर्वोच्च प्राथमिकता वाले सॉर्ट करने के साथ। यह प्रत्येक कॉलम पर दिशा ग्लिफ भी दिखाता है। – Mh4

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