Как сделать сортировку DataGridVewLinkColumn с остальной частью DataGridView

Я заполнил DataGridView DataTable в качестве источника данных. Этот источник данных имеет столбец с комментариями. Я скрываю этот столбец как часть требований и добавляю новый DataGridVewLinkColumn, чтобы при нажатии на него пользователь мог видеть этот комментарий.

Моя проблема заключается в том, что, когда я сортирую, щелкая любой заголовок в DataGridView, все ссылки DataGridViewLinkColumn исчезают. Я установил SortMode на Automatic в этом LinkColumn, но мне кажется, что мне нужно сделать что-то еще, потому что, как только я нажимаю на заголовки из других столбцов в Grid, ссылки исчезают.

Кто-нибудь знает, как я могу убедиться, что при сортировке DataGridView столбец ссылок сортируется соответствующим образом?

Большое спасибо

ОК, я понял это. Проблема заключается в том, что я использовал DataTable в качестве источника данных, он был привязан к сетке, и нет никакого способа добавить дополнительный столбец в источник сетки, который уже связан, и ожидать, что он будет привязан к источнику. Чтобы решить эту проблему, я просто изменил таблицу данных. Добавьте дополнительный столбец в таблицу данных со строками, которые будут ссылками в DataGridView, и заполняйте DataGridView программно, как рекомендуется в http://msdn.microsoft.com/en-us/library/bxt3k60s(v=vs.90).aspx

1 ответ

Решение

Режимы сортировки столбцов в элементе управления Windows Forms DataGridView

При сортировке элемента управления DataGridView, содержащего как связанные, так и несвязанные столбцы, значения в несвязанных столбцах не могут поддерживаться автоматически. Чтобы сохранить эти значения, вы должны реализовать виртуальный режим, установив для свойства VirtualMode значение true и обработав события CellValueNeeded и CellValuePressed.

Это немного сложно, поэтому самое простое решение - добавить дополнительный столбец в DataTable.

Я оставлю пример ниже для дальнейшего использования.

Очки:

  • VirtualMode должно быть правдой.
  • CellValueNeeded должны быть обработаны правильно, чтобы показать указанные значения ячеек.
  • ColumnHeaderMouseClick должен обрабатываться правильно, чтобы сортировать по несвязанным столбцам и показывать глифы сортировки.

Замечания:

  • DataGridView в этом примере предназначен только для чтения, чтобы упростить задачу.

Этот пример формы содержит:

  • Типизированный DataSet, который имеет DataTable1 с колоннами ID(Строка), Comment(Строка):

    private DataSet1 dataSet1;
    
  • BindingSource:

    private BindingSource dataTable1BindingSource;
        .DataMember = "DataTable1";
        .DataSource = this.dataSet1;
    
  • DataGridView:

    private DataGridView dataTable1DataGridView;
        .DataSource = this.dataTable1BindingSource;
        .VirtualMode = true;
        .CellValueNeeded += this.dataTable1DataGridView_CellValueNeeded;
        .ColumnHeaderMouseClick += this.dataTable1DataGridView_ColumnHeaderMouseClick;
        .ReadOnly = true;
        .AllowUserToAddRows = false;
        .AllowUserToDeleteRows = false;
    
  • Его столбцы:

    private DataGridViewTextBoxColumn iDDataGridViewTextBoxColumn;      // bound column
    private DataGridViewTextBoxColumn commentDataGridViewTextBoxColumn; // bound column
    private DataGridViewLinkColumn linkColumn;                          // unbound column
        .SortMode = DataGridViewColumnSortMode.Automatic;
    

И здесь идет код:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    // Hold the link texts, in a dictinary
    // keyed by ID (= unique key in DataTable1), to be bound to each row.
    private SortedDictionary<string, string> _linkTexts
        = new SortedDictionary<string, string>();

    private void Form1_Load(object sender, EventArgs e)
    {
        // Bound data sample
        this.dataSet1.DataTable1.AddDataTable1Row("1", "Comment1");
        this.dataSet1.DataTable1.AddDataTable1Row("2", "Comment2");
        this.dataSet1.DataTable1.AddDataTable1Row("3", "Comment3");

        // Unbound data sample
        this._linkTexts.Add("1", "linkA");
        this._linkTexts.Add("2", "linkC");
        this._linkTexts.Add("3", "linkB");
    }

    // Handles ColumnHeaderMouseClick to do custom sort.
    private void dataTable1DataGridView_ColumnHeaderMouseClick(
        object sender, DataGridViewCellMouseEventArgs e)
    {
        // When the unbound column header is clicked,
        if (e.ColumnIndex == this.linkColumn.Index)
        {
            // Create a new DataView sorted by the link text
            // with toggling the sort order.
            DataView newView;
            switch (this.linkColumn.HeaderCell.SortGlyphDirection)
            {
                case SortOrder.None:
                case SortOrder.Descending:
                    this.linkColumn.HeaderCell.SortGlyphDirection
                        = SortOrder.Ascending;
                    newView = this.dataSet1.DataTable1
                        .OrderBy(row => this._linkTexts[row.ID])
                        .AsDataView();
                    break;

                default:
                    this.linkColumn.HeaderCell.SortGlyphDirection
                        = SortOrder.Descending;
                    newView = this.dataSet1.DataTable1
                        .OrderByDescending(row => this._linkTexts[row.ID])
                        .AsDataView();
                    break;
            }

            // Set it as DataSource.
            this.dataTable1BindingSource.DataSource = newView;

            // Clear sort glyphs on the other column headers.
            foreach (DataGridViewColumn col
                     in this.dataTable1DataGridView.Columns)
            {
                if (col != this.linkColumn)
                    col.HeaderCell.SortGlyphDirection = SortOrder.None;
            }
        }
        // The bound column header is clicked,
        else
        {
            // Sorting has done automatically.
            // Reset the sort glyph on the unbound column.
            this.linkColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
        }
    }

    // Handles CellValueNeeded to show cell values in virtual mode.
    private void dataTable1DataGridView_CellValueNeeded(
        object sender, DataGridViewCellValueEventArgs e)
    {
        // Extract the bound row from the current data view.
        DataSet1.DataTable1Row row
            = (this.dataTable1BindingSource[e.RowIndex] as DataRowView)
              .Row as DataSet1.DataTable1Row;

        // For the unbound column,
        if (e.ColumnIndex == this.linkColumn.Index)
        {
            if (row.IsIDNull())
                e.Value = DBNull.Value;
            else
                // get the value from the dictionary.
                e.Value = this._linkTexts[row.ID];
        }
        // For the bound columns,
        else
        {
            // get the value from the data source.
            string propName = this.dataTable1DataGridView
                              .Columns[e.ColumnIndex].DataPropertyName;
            e.Value = row[propName];
        }
    }
}
Другие вопросы по тегам