0

我有一个 DataGrid,在填充后我想将其导出为 Excel 格式。到目前为止,我能够做到这一点。当我尝试对列顺序进行排序时,我的问题就来了。标头是根据正确的顺序构建的,但 DataGridRows 不是。

图像显示了最终结果:

列排序

在此示例中,我将“ID Equipa”列与“Tipo Entidade”交换,但是在 excel 文件(右侧)中,行值继续,就好像在标题更新良好时没有发生任何变化一样。

不知道这是否有帮助,但我的“ExportToExcel”类基于此项目ExportToExcel 项目,但没有使用它的类标识符

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

我创造了这个

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

我认为问题出在我的“dataToFill”参数中,因为它保持默认的单元格顺序并且在列排序事件后不会更新。

我不明白为什么会这样。如果有人能对这个问题有所了解,我将不胜感激。

谢谢

编辑:

按照 Sheridan 的建议,我发布了一些额外的代码。

这就是我提取 DataGrid 行的方式

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;
            }
        }
    }

这就是我如何激活 ExportToExcel 类

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());
            }
        }
    }

下一点是我对前面提到的 CodeProject 项目中的原始代码的覆盖

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);
    }
4

1 回答 1

0

你真的不应该使用你不理解的代码......这就是使用你在互联网上找到的代码的问题。

如果您查看该CreateHeader方法,您将看到标题标题来自该行:

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

这只是遍历您的类中定义的属性,与您的排序数据无关。要以简单的方式解决您的问题,只需重新排序headerInfo变量以匹配您的排序数据。

但是,我建议您以更困难的方式解决您的问题,以了解您的代码在做什么,然后根据您的要求进行调整。

更新>>>

在看到您正在遍历您的DataGrid.ItemsSource集合后,我猜这是您的问题,因为该集合在 UI 中排序后将保持不变。您有几个选择...一种方法是更新绑定到ItemsSource属性的实际集合,以响应用户对网格中各种标题的点击 - 这样,您当前的数据提取方法就可以工作。

也许更常用的方法是在您的集合和...之间使用一个CollectionViewSource对象...请参阅 MSDN 上的Class页面以获取有关此内容的帮助,包括 XAML 示例。基本上,使用此方法时,您可以从对象中获取处于排序(和过滤)状态的集合副本。DataGrid.ItemsSourceCollectionViewSourceCollectionViewSource

于 2013-10-11T13:25:19.187 回答