C# How to populate a 3 column listView from TMDB data

Hi
as a learning exercise I'm building an windows form app using The Movie  Database API and LordMike C#.Net library for TheMovieDB.

User hits a button and runs a search populating a 3 column listView (Id, Title,Thumbnail)  see pic

I'm struggling to populate the listview with the id and thumbnail columns

Ideally I would like to hide the ID column but need it because  to access more of the movies properties you needs its Id

On clicking a row I access said id.

I'm hopping someone can explain what I'm doing wrong

Thank you


namespace WindowsFormsApplication1
{
    public partial class MiovieForm : Form
    {
        string ImgPath = "http://image.tmdb.org/t/p/";

            TMDbClient client = new TMDbClient("Your API Key");
        public MiovieForm()
        {
            InitializeComponent();
        }

  private void SearchTitlebutton_Click(object sender, EventArgs e)
        {
            string title = TitletextBox.Text;
            SearchContainer<SearchMovie> results = client.SearchMovieAsync(title).Result;
            ResultsLabel.Text = ($"Got {results.Results.Count:N0} of {results.TotalResults:N0} results");

            foreach (SearchMovie result in results.Results)
            {
                
                string ImgUrl =  ImgPath + "w92" + result.PosterPath; // gets an thumb nail of the poster
                TitlelistView.Items.Add(new ListViewItem(new int[] { "1", result.Id })); // red line under "1" I thought this was the column number
                TitlelistView.Items.Add(new ListViewItem(new string[] { "2", result.Title }));
                TitlelistView.Items.Add(new ListViewItem(new string[] { "3", Image.FromStream(LoadImage(ImgUrl)}));// red line under LoadImage see pic
                
            }
        }

        private void TitlelistBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            ResultsLabel.Text = ("You chose " + TitlelistBox.SelectedIndex);

        }
 //  removed empty code for here
        private Image LoadImage(string url)
        {
            System.Net.WebRequest request =
                System.Net.WebRequest.Create(url);

            System.Net.WebResponse response = request.GetResponse();
            System.IO.Stream responseStream =
                response.GetResponseStream();

            Bitmap bmp = new Bitmap(responseStream);

            responseStream.Dispose();

            return bmp;
        }
 }
}

Open in new window

LoadImg.JPGColums.JPG
LVL 1
trevor1940Asked:
Who is Participating?
 
it_saigeDeveloperCommented:
This should point you down the right path:

Form1.cs -
using Newtonsoft.Json;
using System;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using TMDbLib.Client;
using TMDbLib.Objects.General;
using TMDbLib.Objects.Search;

namespace EE_Q29087098
{
    public partial class Form1 : Form
    {
        const string imagePath = "http://image.tmdb.org/t/p/";
        JsonSerializer serializer = default(JsonSerializer);
        TMDbClient client = default(TMDbClient);

        public Form1()
        {
            InitializeComponent();
            serializer = new JsonSerializer();
            client = new TMDbClient("<your api key here>", false, "api.themoviedb.org", serializer);
            lvResults.Columns.AddRange((from column in new[] { "ID", "Title", "Release Date", "Overview", "Media Type" }
                                        select new ColumnHeader { Name = column.Replace(" ", ""), Text = column, Width = 100 }).ToArray());
        }

        private void OnClick(object sender, EventArgs e)
        {
            if (sender is Button)
            {
                var btn = sender as Button;
                if (btn.Equals(btnSearch) && !string.IsNullOrWhiteSpace(tbSearch.Text))
                {
                    SearchContainer<SearchMovie> results = client.SearchMovieAsync(tbSearch.Text).Result;
                    lblResults.Text = $"Retrieved {results.Results.Count:N0} of {results.TotalResults:N0} results...";
                    foreach (SearchMovie result in results.Results)
                    {
                        if (!imgResults.Images.ContainsKey($"{imagePath}w92{result.PosterPath}"))
                            imgResults.Images.Add($"{imagePath}w92{result.PosterPath}", LoadImage($"{imagePath}w92{result.PosterPath}"));
                        lvResults.Items.Add(new ListViewItem(new[] { result.Id.ToString(), result.Title.ToString(), result.ReleaseDate.ToString(), result.Overview.ToString(), result.MediaType.ToString() }) { ImageKey = $"{imagePath}w92{result.PosterPath}" });
                    }
                }
            }
            else if (sender is ToolStripItem)
            {
                var tsi = sender as ToolStripItem;
                if (tsi.Tag != null && tsi.Tag is View)
                {
                    lvResults.View = (View)tsi.Tag;
                }
            }
        }

        private void OnLoad(object sender, EventArgs e)
        {
            foreach (var view in Enum.GetValues(typeof(View)).Cast<View>())
            {
                var item = new ToolStripMenuItem { Name = $"tsm{Enum.GetName(typeof(View), view)}", Text = Enum.GetName(typeof(View), view), Tag = view };
                item.Click += OnClick;
                cmsListView.Items.Add(item);
            }
        }

        private void OnMouseClick(object sender, MouseEventArgs e)
        {
            if (sender is ListView && e.Button == MouseButtons.Right)
            {
                var lv = sender as ListView;
                if (lv.FocusedItem.Bounds.Contains(e.Location))
                    cmsListView.Show(Cursor.Position);
            }
        }

        Image LoadImage(string url)
        {
            Bitmap result = default(Bitmap);
            try
            {
                WebRequest request = WebRequest.Create(url);
                using (var response = request.GetResponse())
                using (var stream = response.GetResponseStream())
                {
                    result = new Bitmap(stream);
                }
            }
            catch { /* Not every movie has a poster */; }
            return result;
        }
    }
}

Open in new window

Form1.Designer.cs -
namespace EE_Q29087098
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.lblSearch = new System.Windows.Forms.Label();
            this.tbSearch = new System.Windows.Forms.TextBox();
            this.btnSearch = new System.Windows.Forms.Button();
            this.lvResults = new System.Windows.Forms.ListView();
            this.imgResults = new System.Windows.Forms.ImageList(this.components);
            this.lblResults = new System.Windows.Forms.Label();
            this.cmsListView = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.SuspendLayout();
            // 
            // lblSearch
            // 
            this.lblSearch.AutoSize = true;
            this.lblSearch.Location = new System.Drawing.Point(9, 15);
            this.lblSearch.Name = "lblSearch";
            this.lblSearch.Size = new System.Drawing.Size(87, 13);
            this.lblSearch.TabIndex = 0;
            this.lblSearch.Text = "Search Titles for:";
            // 
            // tbSearch
            // 
            this.tbSearch.Location = new System.Drawing.Point(102, 12);
            this.tbSearch.Name = "tbSearch";
            this.tbSearch.Size = new System.Drawing.Size(495, 20);
            this.tbSearch.TabIndex = 1;
            // 
            // btnSearch
            // 
            this.btnSearch.Location = new System.Drawing.Point(603, 10);
            this.btnSearch.Name = "btnSearch";
            this.btnSearch.Size = new System.Drawing.Size(75, 23);
            this.btnSearch.TabIndex = 2;
            this.btnSearch.Text = "Search";
            this.btnSearch.UseVisualStyleBackColor = true;
            this.btnSearch.Click += new System.EventHandler(this.OnClick);
            // 
            // lvResults
            // 
            this.lvResults.LargeImageList = this.imgResults;
            this.lvResults.Location = new System.Drawing.Point(12, 39);
            this.lvResults.Name = "lvResults";
            this.lvResults.Size = new System.Drawing.Size(666, 337);
            this.lvResults.SmallImageList = this.imgResults;
            this.lvResults.LargeImageList = this.imgResults;
            this.lvResults.TabIndex = 3;
            this.lvResults.UseCompatibleStateImageBehavior = false;
            this.lvResults.View = System.Windows.Forms.View.Details;
            this.lvResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.OnMouseClick);
            // 
            // imgResults
            // 
            this.imgResults.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
            this.imgResults.ImageSize = new System.Drawing.Size(16, 16);
            this.imgResults.TransparentColor = System.Drawing.Color.Transparent;
            // 
            // lblResults
            // 
            this.lblResults.AutoSize = true;
            this.lblResults.Location = new System.Drawing.Point(13, 391);
            this.lblResults.Name = "lblResults";
            this.lblResults.Size = new System.Drawing.Size(0, 13);
            this.lblResults.TabIndex = 4;
            // 
            // cmsListView
            // 
            this.cmsListView.Name = "contextMenuStrip1";
            this.cmsListView.Size = new System.Drawing.Size(61, 4);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(690, 416);
            this.Controls.Add(this.lblResults);
            this.Controls.Add(this.lvResults);
            this.Controls.Add(this.btnSearch);
            this.Controls.Add(this.tbSearch);
            this.Controls.Add(this.lblSearch);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.OnLoad);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label lblSearch;
        private System.Windows.Forms.TextBox tbSearch;
        private System.Windows.Forms.Button btnSearch;
        private System.Windows.Forms.ListView lvResults;
        private System.Windows.Forms.ImageList imgResults;
        private System.Windows.Forms.Label lblResults;
        private System.Windows.Forms.ContextMenuStrip cmsListView;
    }
}

Open in new window

Which produces the following output -Capture.PNGEven though you didn't request it, I also added a context menu so that you could change the view of the ListView:Capture.PNG
-saige-
0
 
AndyAinscowFreelance programmer / ConsultantCommented:
Have a look in the documentation:
https://msdn.microsoft.com/en-us/library/system.windows.forms.listview.items(v=vs.110).aspx

There is example code there to show you what you want to do.
0
 
trevor1940Author Commented:
Hi

I created a new project with a button to call the "CreateMyListView" in the examlep but that example produces an error



Error
CS0118  C# 'ListView' is a namespace but is used like a type

At this line
  ListView listView1 = new ListView();

Open in new window

0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
AndyAinscowFreelance programmer / ConsultantCommented:
Forget the create a new list view part.  Look at how items and subitems are added.
0
 
trevor1940Author Commented:
Wow thank you very much

You've made a C# newbie happy it'll take me a while to study it

This might be unorthodox would you be able to help with my other C#

https://www.experts-exchange.com/questions/29086688/C-How-to-populate-a-listbox-from-an-SQL-query.html

Thank you
0
 
AndyAinscowFreelance programmer / ConsultantCommented:
Some nice code from it_saige but do you understand what was wrong with your original code and how to fix it?  (You need to learn to crawl before you can run).

ps. Your other question is caused by a lack of basic knowledge.  Consider going on a beginners course and/or reading books about programming.
0
 
trevor1940Author Commented:
Andy

To answer your question

I can see where I'm going wrong
There are bits of it_sage code that I don't understand the need for

TheMovieDB API returns data in JSON and client = new TMDbClient is a  object  so I'm assuming  serializer = new JsonSerializer();  converts the JSON to an object

I'm also unsure why you need to convert everything to a string before adding to the ListView eg. result.Id.ToString()  This Id is an integer if you want to get other info about the film like cast list you need to pass back an integer to the API
0
 
it_saigeDeveloperCommented:
To answer your observations...  

TheMovieDB API returns data in JSON and client = new TMDbClient is a  object  so I'm assuming  serializer = new JsonSerializer();  converts the JSON to an object.
I used the full signature of the TMDbClient constructor.  As such the construstor requires that a JsonSerializer be present as one of the parameters.  I did this in case I needed to tweak the JsonSerializer.
I'm also unsure why you need to convert everything to a string before adding to the ListView eg. result.Id.ToString()  This Id is an integer if you want to get other info about the film like cast list you need to pass back an integer to the API
You are most correct, however, the control that you chose to display your data is a ListView.  The Add method for a ListviewItemCollection accepts the following:Capture.PNGOf those, I chose to use the Add(ListViewItem) version because you wanted to display column based data.  The ListViewItem constructors have many different options but none of them allow for anything other than a string to represent subitems (subitems are what contain the column based data as a 1-to-1 match, e.g. First sub item is mapped to the first column header, Second sub item is mapped to the second column header, etc.).

-saige-
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.