Integrations

Searching Your YouTube Channel and Exporting Video Info

Complete Program

Here is the overall structure of the two-step workflow. Each piece is broken down and explained below.

using GenerallyPositive;

using GenerallyPositive.Browser;

using GenerallyPositive.GPALForm;

using static GenerallyPositive.Enums;


GPAL

.WithInformationHandler(OnGPALEvent)

.WithExceptionHandler(OnGPALEvent);


// Step 1: Google OAuth credentials

GPAL.Form

.WithTitle("YouTube Search -- Step 1 of 2: Google Credentials")

.WithWidth(520).WithHeight(310)

.WithFormControl(GPAL.LabelFor("Client ID:"))

.WithFormControl(clientIdInput)

.WithFormControl(GPAL.LabelFor("Client Secret:"))

.WithFormControl(clientSecretInput)

.WithFormControl(GPAL.LabelFor("Refresh Token:"))

.WithFormControl(refreshTokenInput)

.WithFormControl(connectBtn)

.WithFormControl(cancelCredBtn)

.ShowDialog();


if (!credConnected) return;


// Step 2: search and export

GPAL.Form

.WithTitle("YouTube Search -- Step 2 of 2: Search & Export")

.WithWidth(820).WithHeight(680)

.WithFormControl(searchTab)

.WithFormControl(GPAL.LabelFor("Search term:"))

.WithFormControl(searchInput)

.WithFormControl(searchBtn)

.WithFormControl(GPAL.LabelFor("Results (check items to include):"))

.WithFormControl(resultsList)

.WithFormControl(selectAllBtn)

.WithFormControl(selectNoneBtn)

.WithFormControl(getInfoBtn)

.WithFormControl(detailsTab)

.WithFormControl(detailsBox)

.WithFormControl(GPAL.LabelFor("Fields to export:"))

.WithFormControl(cbTitle)

.WithFormControl(cbDescription)

.WithFormControl(cbTags)

.WithFormControl(cbUrl)

.WithFormControl(cbPublished)

.WithFormControl(cbVideoId)

.WithFormControl(GPAL.LabelFor("Format:"))

.WithFormControl(formatCombo)

.WithFormControl(saveBtn)

.WithFormControl(statusStrip)

.ShowDialog();

Searching for Videos by Keyword

GPAL.YouTube.WithCredentials sets the active Google credential, WithSearchTerms supplies the keyword query, and GetResults populates an out parameter with a list of YouTubeVideoInfo objects. Each result carries a title, video ID, and published date -- enough to populate the results ListView before the user asks for full details.

GPAL.YouTube

.WithCredentials(credentials)

.WithSearchTerms(searchTerm)

.GetResults(out List<YouTubeVideoInfo> results);

Fetching Full Video Info for Selected Items

Search results only include summary fields. To get the full description, tags, and other metadata, the workflow calls GetResults again with WithVideoId for each checked item. Multiple video IDs are chained onto the same IGPALYouTube instance in a loop -- GPAL accumulates them and fetches all in one call.

IGPALYouTube yt = GPAL.YouTube.WithCredentials(credentials);

foreach (string id in checkedVideoIds)

yt = yt.WithVideoId(id);

yt.GetResults(out List<YouTubeVideoInfo> details);

NOTE

The workflow keeps searchResults (summary only) and detailResults (full info) as separate lists. The Search button populates searchResults; Get Video Info populates detailResults from the checked subset. This avoids fetching full details for videos the user does not need.

Exporting with GPAL.Converter

Once full video info is loaded, the user picks which fields to include via checkboxes and chooses an output format from a ComboBox. The workflow builds an IGPALGrid from the selected fields, then passes it to GPAL.Converter with the chosen DataFormat and a SaveFileDialog-supplied output path. The same grid and Converter chain works for CSV, JSON, XML, YAML, HTML, or tab-delimited output -- only the DataFormat enum value changes.

IAllowGridActions<string> grid = GPAL.Grid.AddRow(headers);

foreach (YouTubeVideoInfo v in detailResults)

grid = grid.AddRow(BuildRow(v));


IGPALGrid<string> csvGrid = grid.ToGPALObject();


GPAL.Converter

.WithInput(csvGrid)

.WithOutputType(DataFormat.CSV)

.WithFirstLineHasColumnNames(true)

.SaveTo((GPALFile)outputPath);

A Checked ListView for Multi-Selection

The results list is a GPALListView built with WithCheckBoxes(), giving each row its own checkbox independent of row selection. The workflow stores the video ID in each ListViewItem.Tag so the Get Video Info handler can collect checked IDs without a separate mapping structure. The ItemChecked event, wired in the same chain with WithCallback and ForEvent(ControlEventType.ItemChecked), enables or disables the Get Video Info button based on whether at least one item is checked.

GPALListView resultsList = GPAL.ListView

.WithColumns("Title", "Published", "Video ID")

.WithView(ListViewMode.Details)

.WithFullRowSelect(true)

.WithCheckBoxes()

.WithHeight(260)

.WithCallback<ItemCheckedEventHandler>((s, ev) => UpdateGetInfoState())

.ForEvent(ControlEventType.ItemChecked)

.WithName("results")

.ToGPALObject();


// Populate:

ListView lv = (ListView)resultsList.WindowsControl;

foreach (YouTubeVideoInfo v in results)

{

var item = new ListViewItem(v.Title) { Tag = v.VideoId };

item.SubItems.Add(v.PublishedAt?.ToString("yyyy-MM-dd") ?? string.Empty);

item.SubItems.Add(v.VideoId);

lv.Items.Add(item);

}

WARNING

The search runs on a background thread, and a WinForms ListView can only be changed on the thread that created it. The workflow hands the fill to the UI thread with BeginInvoke when InvokeRequired is true, then adds the items.

💬 Ask GPAL