【问题标题】:DataContext/DataGrid creating duplicate rowsDataContext/DataGrid 创建重复行
【发布时间】:2016-09-19 04:57:37
【问题描述】:

几个小时以来,我一直在绞尽脑汁想弄清楚是什么原因造成的。我有一个 Access 数据库,它在 C#/WPF 中提供一个 DataGrid。我正在使用一个 DataTable 馈送到自定义类中对 CollectionView 进行分页,该类馈送到绑定到 DataGrid 的 DataContext 中。从程序启动到 DataGrid 的绘制,我一直跟踪这一点,并且始终存在正确的行数(使用 MessageBox.Show(CollectionView.Count.ToString()) 来验证它)。即使在绘制 DataGrid 之后也有正确数量的项目(200),所以我认为这一定是 DataGrid 在通过 Pagination 类运行它们后如何显示项目的问题,但我似乎找不到任何地方问题可能源于。有人可以看看这段代码,看看他们是否注意到任何可能导致这种情况的东西?

关于显示重复项的几点说明:如果我在方法调用中更改 itemsPerPage 值,它会影响重复项的分离方式。如果是每页 200 个,则一组中有 8 个重复项。每页 100 个导致一行 4 个重复,然后是另一个 4 个,然后是第一个重复 4 个。像这样:

  • 200 itemsPerPage: aaaaaaaa bbbbbbbb cccccccc dddddddd
  • 100 itemsPerPage: aaaa bbbb aaaa bbbb cccc dddd cccc dddd

显然这些是行,所以它们向下而不是向左,但这个概念应该很清楚。

更新:我之前忘了提,但 Pagination 类是基于对这个问题的回答:How can I paginate a WPF DataGrid?

DataGrid XAML:

<DataGrid x:Name="instrumentIdDataGrid" ColumnWidth="Auto" ColumnHeaderStyle="{StaticResource datagridCenterHeaderStyle}" CellStyle="{StaticResource datagridCenterCellStyle}"
                      HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Margin="5,5,5,5" AutoGenerateColumns="False" Padding="10"
                      AutoGeneratingColumn="instrumentIdDataGrid_AutoGeneratingColumn" ItemsSource="{Binding}">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="Agent TID" Binding="{Binding AgentTID}" />
                            <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}" />
                            <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" />
                            <DataGridTextColumn Header="Team" Binding="{Binding Team}" />
                            <DataGridTextColumn Header="Instrument ID" Binding="{Binding InstrumentID}" />
                            <DataGridTextColumn Header="On-Dialer" Binding="{Binding OnDialerExtension}" />
                            <DataGridTextColumn Header="Off-Dialer" Binding="{Binding OffDialerExtension}" />
                        </DataGrid.Columns>
                    </DataGrid>

DataTable 加载方法:(目前只有instruments DataGrid 使用分页,dialerRecords 没有,也可以。)

private void InitializeDataTables()
    {
        FillDataTable(dialerRecords, @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + backendFilePath + ";User Id=;Password=;", "SELECT * FROM DialerRecords");
        FillDataTable(instruments, @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + backendFilePath + ";User Id=;Password=;", "SELECT * FROM InstrumentIDs");

        this.instrumentCollectionView = new PagingCollectionView(instruments.DefaultView, 20);

        instrumentIdDataGrid.DataContext = instrumentCollectionView;
        dialerRecordsDataGrid.DataContext = dialerRecords.DefaultView;
    }

private void FillDataTable(System.Data.DataTable table, string connectionString, string queryString)
    {
        using (OleDbConnection connection = new OleDbConnection(connectionString))
        {
            connection.Open();

            using (OleDbDataAdapter adapter = new OleDbDataAdapter(queryString, connection))
            {
                adapter.Fill(table);
            }
        }
    }

分页类

public class PagingCollectionView : ListCollectionView
{
    private readonly IList _innerList;
    private readonly int _itemsPerPage;

    private int _currentPage = 1;

    public PagingCollectionView(IList innerList, int itemsPerPage) : base(innerList)
    {
        this._innerList = innerList;
        this._itemsPerPage = itemsPerPage;
    }

    public override int Count
    {
        get
        {
            if (this._innerList.Count == 0)
                return 0;
            if(this._currentPage < this.PageCount)
            {
                return this._itemsPerPage;
            }
            else
            {
                int itemsLeft = this._innerList.Count % this._itemsPerPage;
                if (0 == itemsLeft)
                {
                    return this._itemsPerPage;
                }
                else
                {
                    return itemsLeft;
                }
            }                
        }
    }

    public int CurrentPage
    {
        get { return this._currentPage; }
        set
        {
            this._currentPage = value;
            this.OnPropertyChanged(new PropertyChangedEventArgs("CurrentPage"));
        }
    }

    public int ItemsPerPage
    {
        get
        {
            return this._itemsPerPage;
        }
    }

    public int PageCount
    {
        get
        {
            int end = this._currentPage * this._itemsPerPage - 1;
            return (end > this._innerList.Count) ? this._innerList.Count : end;
        }
    }

    private int StartIndex
    {
        get
        {
            return (this._currentPage - 1) * this._itemsPerPage;
        }
    }

    public override object GetItemAt(int index)
    {
        int offset = index & (this._itemsPerPage);
        return this._innerList[this.StartIndex + offset];
    }

    public void MoveToNextPage()
    {
        if (this._currentPage < this.PageCount)
        {
            this.CurrentPage += 1;
        }
        this.Refresh();
    }

    public void MoveToPreviousPage()
    {
        if(this._currentPage > 1)
        {
            this.CurrentPage -= 1;
        }
        this.Refresh();
    }
}

【问题讨论】:

  • 先试试这个看看会发生什么。摆脱这个标记 AutoGeneratingColumn="instrumentIdDataGrid_AutoGeneratingColumn"
  • 删除标记导致同样的问题,没有变化。我确实怀疑这可能是问题所在,因此我将 AutoGenerateColumns 更改为 False 而之前它是真的。我当时并不积极,但我认为更改为False 会阻止事件触发。很高兴知道情况确实如此,我仍然很感激这个建议! :)
  • 好,试试这个,摆脱分页,直接绑定到仪器集合视图的内容。
  • 这实际上是我最初所拥有的,在添加 Paging 类之前(我以为我已经把它放在原始问题中但一定忘记了)。在分页类之前,它工作得很好,没有重复。添加分页类的唯一原因是因为使 DataGrid 成为焦点时的加载时间非常长,大约为 90-120 秒。我尝试了几种方法来减少它,但没有任何效果,所以我搜索并找到了分页类。基于此,我确定问题一定出在分页类中,但我不知道是什么原因造成的。
  • 好的,我刚刚发现了问题。我回去仔细检查了原始问题的代码,发现我在 Paging 类中混合了两种方法,并在另一种方法中输入了错误的运算符。基本上我合并了EndIndexPageCount 方法。无论如何,感谢您的帮助,我真的很感激,它让我回顾了代码并进行了比较,从而找到了问题。 :)

标签: c# wpf datatable pagination datacontext


【解决方案1】:

所以问题似乎是一个简单的错误输入案例。当我更新问题以反映时,我在上一个问题中找到了 Paging 类。显然,当我将它复制到 Visual Studio 中时,我混合了两种方法,这不知何故导致了这个问题。为了将来参考,我在下面发布了相关的方法。

    public int PageCount
    {
        get
        {
            return (this._innerList.Count + this._itemsPerPage - 1) / this._itemsPerPage;
        }
    }

    public int EndIndex
    {
        get
        {
            int end = this._currentPage * this._itemsPerPage - 1;
            return (end > this._innerList.Count) ? this._innerList.Count : end;
        }
    }

我已将EndIndex 方法的内容放在PageCount 方法中,而将EndIndex 方法完全排除在外。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-07
    • 2010-11-01
    • 2011-10-28
    • 2012-01-16
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    相关资源
    最近更新 更多