def _to_dataframe_tabledata_list(self, dtypes, progress_bar=None):
        """Use (slower, but free) tabledata.list to construct a DataFrame."""
        column_names = [field.name for field in self.schema]
        frames = []

        for page in iter(self.pages):
            current_frame = self._to_dataframe_dtypes(page, column_names, dtypes)
            frames.append(current_frame)

            if progress_bar is not None:
                # In some cases, the number of total rows is not populated
                # until the first page of rows is fetched. Update the
                # progress bar's total to keep an accurate count.
                progress_bar.total = progress_bar.total or self.total_rows
                progress_bar.update(len(current_frame))

        if progress_bar is not None:
            # Indicate that the download has finished.
            progress_bar.close()

        return pandas.concat(frames)