使用WPF + XAML Syncfusion.SfGrid.WPF组合表格中单元格的问题

问题描述 投票:0回答:1

我有一个问题3天都无法处理。听起来很简单,但事实上却复杂得多。我有一个应用程序,它从 Excel 文件中获取数据并将其存储在数据库中,然后该应用程序使用这些数据形成自己的表。一切都会好起来的,但是表中的一个字段无法管理。结构本身如下:4 个主柱。第一列存储帐号、账户组以及一组账户的总金额、类别以及按类别划分的账户组的总金额。所有字段均已正确排列,除了带有类名称的一个字段外,它应该合并所有列。接下来,我将附上应该如何以及实际如何的屏幕截图。

接下来,我将提供我尝试执行此操作的代码,我会立即说,我是新手开发人员,不要严格判断:

{
    public CollectionViewSource AccountsViewSource { get; set; }
    public SfDataGrid DataGrid { get; set; }
    public DisplayDataService(int fileId, SfDataGrid dataGrid)
    {
        AccountsViewSource = new CollectionViewSource();
        DataGrid = dataGrid;
        LoadDataFromDatabase(fileId);
    }

    private void LoadDataFromDatabase(int fileId)
    {
        using (var context = new AppDbContext())
        {
            Console.WriteLine("Создание контекста базы данных...");

            var fileInDb = context.Files.FirstOrDefault(f => f.Id == fileId);

            var accounts = context.Accounts
                .Include(a => a.AccountDetails)
                .Include(a => a.Class)
                .Include(a => a.AccountGroups)
                .Where(a => a.Class.FileId == fileId)
                .ToList();

            var accountDisplayModels = accounts.Select(account => new AccountDisplayModel
            {
                AccountNumber = account.AccountNumber,
                ClassName = account.Class.ClassName,
                AccountGroup = account.AccountGroups.AccountGroup,
                ActiveOpeningBalance = account.AccountDetails.ActiveOpeningBalance,
                PassiveOpeningBalance = account.AccountDetails.PassiveOpeningBalance,
                DebitTurnover = account.AccountDetails.DebitTurnover,
                LoanTurnover = account.AccountDetails.LoanTurnover,
                ActiveClosingBalance = account.AccountDetails.ActiveClosingBalance,
                PassiveClosingBalance = account.AccountDetails.PassiveClosingBalance,
                IsGroupSummary = false,
                IsClassSummary = false,
                DisplayText = account.AccountNumber.ToString()
            }).ToList();

            var displayData = new List<AccountDisplayModel>();

            foreach (var classGroup in accountDisplayModels.GroupBy(a => a.ClassName).OrderBy(g => g.Key))
            {
                displayData.Add(new AccountDisplayModel { DisplayText = classGroup.Key, IsClassHeader = true });

                foreach (var group in classGroup.GroupBy(a => a.AccountGroup).OrderBy(g => g.Key))
                {
                    displayData.AddRange(group.OrderBy(a => a.AccountNumber));

                    var groupSummary = new AccountDisplayModel
                    {
                        DisplayText = $"{group.Key}",
                        ActiveOpeningBalance = group.Sum(a => a.ActiveOpeningBalance),
                        PassiveOpeningBalance = group.Sum(a => a.PassiveOpeningBalance),
                        DebitTurnover = group.Sum(a => a.DebitTurnover),
                        LoanTurnover = group.Sum(a => a.LoanTurnover),
                        ActiveClosingBalance = group.Sum(a => a.ActiveClosingBalance),
                        PassiveClosingBalance = group.Sum(a => a.PassiveClosingBalance),
                        IsGroupSummary = true
                    };

                    displayData.Add(groupSummary);
                }

                var classSummary = new AccountDisplayModel
                {
                    DisplayText = "ПО КЛАССУ",
                    ActiveOpeningBalance = classGroup.Sum(a => a.ActiveOpeningBalance),
                    PassiveOpeningBalance = classGroup.Sum(a => a.PassiveOpeningBalance),
                    DebitTurnover = classGroup.Sum(a => a.DebitTurnover),
                    LoanTurnover = classGroup.Sum(a => a.LoanTurnover),
                    ActiveClosingBalance = classGroup.Sum(a => a.ActiveClosingBalance),
                    PassiveClosingBalance = classGroup.Sum(a => a.PassiveClosingBalance),
                    IsClassSummary = true
                };

                displayData.Add(classSummary);
            }
            DataGrid.QueryCoveredRange += sfDataGrid_QueryCoveredRange;
            AccountsViewSource.Source = displayData;
        }
    }

    private void sfDataGrid_QueryCoveredRange(object sender, GridQueryCoveredRangeEventArgs e)
    {
        var dataGrid = sender as SfDataGrid;

        if (dataGrid == null)
        {
            Console.WriteLine("SfDataGrid не найден.");
            return;
        }

        var recordIndex = dataGrid.ResolveToRecordIndex(e.RowColumnIndex.RowIndex);

        if (recordIndex < 0)
        {
            Console.WriteLine($"Не удалось разрешить индекс записи для строки: {e.RowColumnIndex.RowIndex}");
            return;
        }

        var record = dataGrid.View.Records[recordIndex].Data as AccountDisplayModel;

        if (record != null)
        {
            if (record.DisplayText != null && (record.DisplayText.StartsWith("КЛАСС") || record.IsClassHeader))
            {
                int startColumnIndex = 1;
                int endColumnIndex = dataGrid.Columns.Count;

                e.Range = new CoveredCellInfo(e.RowColumnIndex.RowIndex, startColumnIndex, e.RowColumnIndex.RowIndex, endColumnIndex);
                e.Handled = true;
            }
            else
            {
                Console.WriteLine();
            }
        }
        else
        {
            Console.WriteLine();
        }
    }
} 

要显示的型号:

{
    public int AccountNumber { get; set; }
    public int AccountGroup { get; set; }
    public string ClassName { get; set; }
    public decimal ActiveOpeningBalance { get; set; }
    public decimal PassiveOpeningBalance { get; set; }
    public decimal DebitTurnover { get; set; }
    public decimal LoanTurnover { get; set; }
    public decimal ActiveClosingBalance { get; set; }
    public decimal PassiveClosingBalance { get; set; }
    public bool IsGroupSummary { get; set; }
    public bool IsClassSummary { get; set; }
    public bool IsClassHeader { get; set; }
    public string DisplayText { get; set; }
} 

窗口生成:

{
    public DataDisplayWindow(int fileId)
    {
        InitializeComponent();
        DataContext = new DisplayDataService(fileId, sfDataGrid);
    }
}

XAML代码:

    <DataTemplate x:Key="ClassHeaderCellTemplate">
        <TextBlock Text="{Binding DisplayText}" 
               HorizontalAlignment="Center" 
               VerticalAlignment="Center" 
               Background="LightGray" />
    </DataTemplate>

    <DataTemplate x:Key="NormalCellTemplate">
        <TextBlock Text="{Binding DisplayText}" />
    </DataTemplate>

    <local1:ClassHeaderTemplateSelector x:Key="classHeaderTemplateSelector"
                                   ClassHeaderTemplate="{StaticResource ClassHeaderCellTemplate}" 
                                   NormalTemplate="{StaticResource NormalCellTemplate}" />
</Window.Resources>
<Grid>
    <syncfusion:SfDataGrid x:Name="sfDataGrid"
                   AutoGenerateColumns="False"
                   ItemsSource="{Binding AccountsViewSource.View}"
                   SelectionUnit="Cell"
                   NavigationMode="Cell"
                   AllowEditing="False"
                   AllowDeleting="False"
                   AllowDraggingColumns="False"
                   AllowResizingColumns="True"
                   AllowSorting="True"
                   ShowGroupDropArea="False">
        <syncfusion:SfDataGrid.StackedHeaderRows>
            <syncfusion:StackedHeaderRow>
                <syncfusion:StackedHeaderRow.StackedColumns>
                    <syncfusion:StackedColumn ChildColumns="ActiveOpeningBalance,PassiveOpeningBalance" HeaderText="ВХОДЯЩЕЕ САЛЬДО"/>
                    <syncfusion:StackedColumn ChildColumns="DebitTurnover,LoanTurnover" HeaderText="ОБОРОТЫ"/>
                    <syncfusion:StackedColumn ChildColumns="ActiveClosingBalance,PassiveClosingBalance" HeaderText="ИСХОДЯЩЕЕ САЛЬДО"/>
                </syncfusion:StackedHeaderRow.StackedColumns>
            </syncfusion:StackedHeaderRow>
        </syncfusion:SfDataGrid.StackedHeaderRows>
        <syncfusion:SfDataGrid.Columns>
            <syncfusion:GridTemplateColumn MappingName="DisplayText" HeaderText="Б/сч" 
                                       CellTemplateSelector="{StaticResource classHeaderTemplateSelector}"/>
            <syncfusion:GridTextColumn MappingName="ActiveOpeningBalance" HeaderText="Актив"/>
            <syncfusion:GridTextColumn MappingName="PassiveOpeningBalance" HeaderText="Пассив"/>
            <syncfusion:GridTextColumn MappingName="DebitTurnover" HeaderText="Дебет"/>
            <syncfusion:GridTextColumn MappingName="LoanTurnover" HeaderText="Кредит"/>
            <syncfusion:GridTextColumn MappingName="ActiveClosingBalance" HeaderText="Актив"/>
            <syncfusion:GridTextColumn MappingName="PassiveClosingBalance" HeaderText="Пассив"/>
        </syncfusion:SfDataGrid.Columns>
    </syncfusion:SfDataGrid>
</Grid> 

类选择器:

{
    public DataTemplate ClassHeaderTemplate { get; set; }
    public DataTemplate NormalTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var record = item as AccountDisplayModel;
        if (record != null && record.IsClassHeader)
        {
            return ClassHeaderTemplate;
        }
        else
        {
            return NormalTemplate;
        }
    }
}

该应用程序使用以下库:EF core、Plus、Syncfusion.Grid.WPF

当一个对象具有 Is Class Header = true 属性时,则该对象的字段的所有单元格应合并为一个。但是具有 Is Class Header = true 属性的这种类型的对象分别仅存储在 1 列中,此类对象的第一列应该是整个表格宽度的一列,如屏幕截图所示

我已经尝试了很多选项,对每行代码使用日志记录、调试以及更新可视化组件的不同方法......没有任何帮助。

c# .net wpf xaml syncfusion
1个回答
0
投票

根据报告的场景,结合上述代码片段,发现CoveredCellInfo中sfDatagrid_QueryCoveredRange方法的参数解析存在一些错位。

请注意,CoveredCellInfo 的解析参数应包含四个参数。前两个参数(left 和 right)应考虑列值(startcolumnindex 和 endcolumnindex),而其他两个参数(top 和bottom)应考虑行值(startrowindex 和 endrowindex)。根据这些参数,可以合并单元格。

请参阅随附的测试样品。请看一下这个。

请查找下面附加的 UG 链接以供参考处理“合并单元格”。

UG链接-> enter link description here

请参考输出: enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.