简体   繁体   中英

WPF DataGridRow not updating cell order after column sort

I have a DataGrid that after is populated I want to export it to Excel format. So far I'm able to do that. My problem comes when I try to sort the column order. The header is built according to the right order but the DataGridRows are not.

The image shows the final result:

列排序

In this example I swapped the 'ID Equipa' column with the 'Tipo Entidade', however in the excel file (on the right) the row values continue as if no change ever happened while the header is updated nicely.

Don't know if this helps, but my 'ExportToExcel' class is based on this project ExportToExcel Project but instead of using it's class identifier

public class ExportToExcel<T, U>
where T : class
where U : List<T>
{
    // ...
}

I created this one

public class ExportToExcel
}
    public ExportToExcel(List<DataGridColumn> columns, List<DataGridRow> dataToFill)
        {
            // ...
        }
}

I think the problem is in my 'dataToFill' argument, since it keeps it's default cell order and does not update after a column sort event.

I don't understand why this is happening. I would really appreciate if someone could shed some light at this issue.

Thanks

EDIT:

Following Sheridan's advice I'm posting some extra code.

This is how I extract the DataGrid Rows

public IEnumerable<DataGridRow> GetDataGridRows()
    {
        var itemsSource = dgEntities.ItemsSource as IEnumerable;
        if (null == itemsSource) yield return null;
        foreach (var item in itemsSource)
        {
            var row = dgEntities.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
            if (null != row) 
            {
                if (dgEntities.SelectedItems.Count == 0) yield return row;
                else if (row.IsSelected) yield return row;
            }
        }
    }

And here's how I instaciate the ExportToExcel class

public void ExportToExcel() 
    {
        if (dgEntities.ItemsSource != null)
        {
            try
            {
                BLL.ExportToExcel export = new ExportToExcel(dgEntities.Columns.ToList(), GetDataGridRows().ToList());
                export.GenerateReport();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }
    }

This next bit is my override of the original code from the CodeProject Project I mentioned earlier

private object[] CreateHeader()
    {
        // Create an array for the headers and add it to the
        // worksheet starting at cell A1.
        List<object> objHeaders = new List<object>();
        foreach (DataGridColumn dgc in Columns)
        {
            if (dgc.Visibility == System.Windows.Visibility.Visible) objHeaders.Add(dgc.Header);
            else deletedColumns.Add(dgc.DisplayIndex);
        }

        var headerToAdd = objHeaders.ToArray();
        AddExcelRows("A1", 1, headerToAdd.Length, headerToAdd);
        SetHeaderStyle();

        return headerToAdd;
    }

    private void WriteData(object[] header)
    {
        object[,] objData = new object[DataToFill.Count, header.Length];

        for (int j = 0; j < DataToFill.Count; j++)
        {
            DataGridRow row = DataToFill[j];
            int i = 0;
            for (int x = 0; x < Columns.Count; x++)
            {
                if (!deletedColumns.Contains(x))
                {
                    DataGridCell cell = GetCell(row, j, x);
                    if (cell != null && cell.Content is TextBlock)
                    {
                        objData[j, i] = ((TextBlock)cell.Content).Text;
                        i++;
                    }
                }
            }
        }
        AddExcelRows("A2", DataToFill.Count, header.Length, objData);
        AutoFitColumns("A1", DataToFill.Count + 1, header.Length);
    }

You really shouldn't use code that you don't understand... that's the problem with using bits of code that you find on the internet.

If you look in the CreateHeader method you will see that the header titles come from the line:

PropertyInfo[] headerInfo = typeof(T).GetProperties();

This is just iterating through the properties defined in your class and bear no relevance to your sorted data. To fix your problem the easy way, just re-order the headerInfo variable to match your sorted data.

However, I would recommend that you fix your problem the more difficult way of learning what your code is doing and then adjusting it to your requirements.

UPDATE >>>

After seeing that you are iterating through your DataGrid.ItemsSource collection, I'm guessing that that is your problem, as that collection will remain unchanged after being sorted in the UI. You have a few choices... one method is to update the actual collection that is bound to the ItemsSource property in response to the users' clicks on the various headers in the grid - that way, your current data extraction method would work.

Maybe a more common method to use would be to use a CollectionViewSource object between your collection and the DataGrid.ItemsSource ... see the CollectionViewSource Class page on MSDN for help with this including XAML examples. Basically, when using this method, you can get a copy of the collection in its sorted (and filtered) state from the CollectionViewSource object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM