Entwickler-Ecke

WinForms - library verwenden


greentiger - Fr 16.12.11 22:04
Titel: library verwenden
Guten Abend!

Ich möchte ein Programm schreiben, dass mir Informationen über bestimmte Filme liefert.
Jedoch gibt es ein Problem beim Aufrufen der library.
https://themoviedbapi.codeplex.com/documentation

TheMovieDBLib.dll habe ich als Verweis hinzugefügt + using Verweis aber irgendwie kann er mit

TmdbAPI api = new TmdbAPI("apikey");

nichts anfangen?

MfG greentiger


Christian S. - Fr 16.12.11 22:15

Was heißt "damit kann er nichts anfangen"? Wenn eine Fehlermeldung kommt, ist es nützlich, sie hier mit anzugeben :-)


greentiger - Fr 16.12.11 22:22

Ganz vergessen ;)

Fehlermeldung: "Der Typ- oder Namespacename "TmdbAPI" konnte nicht gefunden werden. (Fehlt eine Using-Direktive oder ein Assemblyverweis?)"


Trashkid2000 - Fr 16.12.11 22:42

Hi,
auf Groß-und-Kleinschreibung muss man schon achten. Denn es heißt:

C#-Quelltext
1:
TmdbApi api = new TmdbApi("apikey");                    
Okay, in der Doku steht es falsch, aber mit IntelliSense kriegt an das ja schnell raus.


greentiger - Fr 16.12.11 22:49

user profile iconTrashkid2000 hat folgendes geschrieben Zum zitierten Posting springen:
Hi,
auf Groß-und-Kleinschreibung muss man schon achten. Denn es heißt:

C#-Quelltext
1:
TmdbApi api = new TmdbApi("apikey");                    
Okay, in der Doku steht es falsch, aber mit IntelliSense kriegt an das ja schnell raus.


Ach, Danke ;)

Ich dachte ich habe irgendeinen blöden Fehler beim Verweis oder so aber das die Doko falsch ist,... :D

MfG


greentiger - Sa 17.12.11 20:31

TmdbMovie[] movies = api.MovieSearch("batman");

Fehlermeldung:
Der Typ System.Collections.Generic.IEnumerable<TheMovieDb.TmdbMovie>" kann nicht implizit in "TheMovieDb.TmdbMovie[]" konvertiert werden. Es ist bereits eine explizite Konvertierung vorhanden. (Möglicherweise fehlt eine Umwandlung.)

In was soll ich sie umwandeln?


Yogu - Sa 17.12.11 20:55

Auch wenn das hier immer mehr in einen Thread mit vielen Themen ausartet:

Du kannst das IEnumerable mit der Erweiterungsmethode ToArray() [http://msdn.microsoft.com/en-us/library/bb298736%28v=VS.90%29.aspx] in ein Array konvertieren. Du könntest movies aber auch gleich in einer foreach-Schleife durchlaufen.


greentiger - Sa 17.12.11 21:06

Danke, habe es einfach mit toArray() gelöst.

Die Doko sollte auch einmal überarbeitet werden ;)

Edit: würdest du es mit einer foeach Schleife so lösen?

C#-Quelltext
1:
2:
3:
4:
foreach (string elemente in movies)
            {
                textBox1.Text = elemente;
            }


MfG


Yogu - Sa 17.12.11 21:19

user profile icongreentiger hat folgendes geschrieben Zum zitierten Posting springen:
würdest du es mit einer foeach Schleife so lösen?

C#-Quelltext
1:
2:
3:
4:
foreach (string elemente in movies)
            {
                textBox1.Text = elemente;
            }


MfG

Die Elemente sind nicht vom Typ string, sondern TmdbMovie, und die Variable hieße besser element. Davon abgesehen, ja.


greentiger - Fr 23.12.11 19:44

Möchte jetzt gerne so vorgehe, dass ich alle gefunden Filme ausgeben und den richtigen Film auswählen kann, anschließend sollen die Infos über den Film erscheinen.

1. Wollte alle gefunden Filme einmal in der textbox1 ausgeben, jedoch kommt er aus der Schleife nicht mehr heraus, die Namen werden richtig aufgerufen aber das Form1 öffnet sich nicht, Fehlermeldung gibt es keine:

C#-Quelltext
1:
2:
3:
4:
foreach (TmdbMovie element in movies)
            {
                textBox1.Text += element.AlternativeName.ToString();                
            }


2. Wie könnte ich das machen, dass beim Klicken/Enter auf den richtigen Film, dass Array bekomme wo der Name gespeichert ist um später die Informatione auszugeben?

Besten Dank im Voraus.

MfG greentiger


Yogu - Fr 23.12.11 20:32

user profile icongreentiger hat folgendes geschrieben Zum zitierten Posting springen:
1. Wollte alle gefunden Filme einmal in der textbox1 ausgeben, jedoch kommt er aus der Schleife nicht mehr heraus, die Namen werden richtig aufgerufen aber das Form1 öffnet sich nicht, Fehlermeldung gibt es keine

Der Code sieht gut aus. Was passiert denn, wenn du einen Haltepunkt setzt und dich per Einzelschritt durcharbeitest? Wo genau hängt er sich da auf?

user profile icongreentiger hat folgendes geschrieben Zum zitierten Posting springen:
2. Wie könnte ich das machen, dass beim Klicken/Enter auf den richtigen Film, dass Array bekomme wo der Name gespeichert ist um später die Informatione auszugeben?

Ich würde vorschlagen, statt der TextBox eine ListBox zu nehmen und einen Eintrag für jeden Film hinzuzufügen. Dann kannst du im SelectedIndexChanged-Ereignis den Namen des neuen Films ermitteln. Das Array muss dann natürlich ein Feld des Formulars sein.

Besser wäre es, eine eigene kleine Klasse zu schreiben, die eine Instanz von TmdbMovie hält und über die Methode ToString den Wert von AlternativeName zurückgibt:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
class MovieListItem {
  public MovieListItem(TmdbMovie movie) {
    Movie = movie;
  }

  public TmdbMovie Movie {get; private set; }

  public string ToString() {
    return Movie.AlternativeName.ToString();
  }
}

Statt dem Namen kannst du nun Instanzen dieser Klasse zur ListBox hinzufügen. In der SelectedIndexChanged-Routine kannst du SelectedItem dann in ein MovieListItem zurückkonvertieren und auf das TmdbMovie-Objekt zugreifen:


C#-Quelltext
1:
2:
MovieListItem listItem = (MovieListItem)listBox1.SelectedItem;
TmdbMovie movie = listItem.Movie;


greentiger - Fr 23.12.11 20:56

Danke für deine Antwort, werde mich über die Feiertage damit bemühen ;)

user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:

Was passiert denn, wenn du einen Haltepunkt setzt und dich per Einzelschritt durcharbeitest? Wo genau hängt er sich da auf?


Ich habe es vorher schon mit Breakpoints getestet, die Filmergebnisse werden richtig abgerufen und auch ausgeben(Messagebox bzw TB1), jedoch ist nach der Schleife schluss. Letzter Wert ist null(siehe Bild) dann müsst er aus der Schleife gehen -> Programm schließt sich.

https://dl.dropbox.com/u/17888900/Filmdatenbank.bmp


Th69 - Fr 23.12.11 21:01

Hallo greentiger,

ein Nullwert kann ja auch nicht als String ausgegeben werden, d.h. du mußt explizit auf 'null' testen.


Yogu - Fr 23.12.11 21:03

user profile icongreentiger hat folgendes geschrieben Zum zitierten Posting springen:
Letzter Wert ist null(siehe Bild)

Da ist element.AlternativeName null, und du rufst element.AlternativeName.ToString() auf - das löst eine NullReferendeException aus, und deshalb wird das Formular nicht angezeigt. Du müsstest abfragen, ob denn AlternativeName null ist.


greentiger - Sa 24.12.11 18:34

Okay, Danke.

Wenn ich null abfange werden alle Filme korrekt ausgegeben.

Empfehlung von Yogu eine Klasse zu erstellen.

Habe jetzt die Klasse erstellt:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
class MovieListItem
    {
        public MovieListItem(TmdbMovie movie)
        {
            Movie = movie;            
        }

        public TmdbMovie Movie { get; private set; }

        public string ToString()
        {
            return Movie.AlternativeName.ToString();
        }
    }


Aufruf:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
            TmdbApi api = new TmdbApi("Key");
            TmdbMovie[] movies = api.MovieSearch("batman").ToArray();
             
            foreach (TmdbMovie element in movies)
            {                       
                listBox1.Items.Add(new MovieListItem(element));
            }


Er gibt mir ganz was anderes aus(Projektname).


Th69 - So 25.12.11 11:29

Hallo,

schau dir mal die Warnung an (oder hast du die etwa ausgeschaltet bzw. nicht gesehen?).
Yogu hatte noch einen kleinen Fehler in seinem Code...
Die Lösung dazu überlasse ich dir als Weihnachtsaufgabe ;-)


Yogu - So 25.12.11 13:20

user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
Yogu hatte noch einen kleinen Fehler in seinem Code...

Man sollte nicht so gedankenlos zwischen C# und Java hin- und herwechseln ;)


greentiger - So 25.12.11 13:57

user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:

schau dir mal die Warnung an (oder hast du die etwa ausgeschaltet bzw. nicht gesehen?).


Der Code ist so wie oben gepostet, bekomme aber keine Warnung.

Edit: Meinst du dies hier?


C#-Quelltext
1:
2:
3:
4:
public new string ToString()
        {
            return Movie.AlternativeName.ToString();
        }


Bei der Ausgabe hat sich jedoch nichts geändert.


Yogu - So 25.12.11 14:10

user profile icongreentiger hat folgendes geschrieben Zum zitierten Posting springen:
Der Code ist so wie oben gepostet, bekomme aber keine Warnung.

Die Warnung ist bei mir jetzt tatsächlich auch nicht gleich gekommen, und als sie dann da war, ist sie nach dem nächsten Compilieren wieder verschwunden. Wie dem auch sei, so lautet sie:

Zitat:
"MovieListItem.ToString()" blendet den vererbten Member "object.ToString()" aus. Damit der aktuelle Member diese Implementierung überschreibt, fügen Sie das override-Schlüsselwort hinzu. Ansonsten fügen Sie das new-Schlüsselwort hinzu.


user profile icongreentiger hat folgendes geschrieben Zum zitierten Posting springen:
Meinst du dies hier?


C#-Quelltext
1:
2:
3:
4:
public [b]new[/b] string ToString()
        {
            return Movie.AlternativeName.ToString();
        }


Bei der Ausgabe hat sich jedoch nichts geändert.

Richtige Baustelle, falsches Baumaterial ;) Du willst keine neue ToString-Methode erstellen, sondern die vorhandene überschreiben, sodass statt der Methode von object deine aufgerufen wird. Also ist override das richtige Schlüsselwort.


greentiger - So 25.12.11 14:37

Okay.

Es kann ja jetzt immer noch null zurückgegeben werden umd das abzufangen hätte ich try and catch verwendet und die Exception gibt den string "null" zurück.
Jedoch brauch ich diesen Wert nicht in der Ausgabe, wie könnte ich verhindern das der Wert ausgegeben wird?

Ich dachte mir ich könnte das Item löschen, bzw abfragen wenn es "null" ist das es nicht erstellt wird, jedoch klappt das nicht so gut, was wäre in diesem Fall die optimale Lösung?


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
public override string ToString()
        {
            try
            {
                return Movie.AlternativeName.ToString();
            }
            catch (NullReferenceException) { return "null";};
        }


Th69 - So 25.12.11 15:16

Hallo greentiger,

klar mußt du dann auch hier auf 'null' prüfen, aber dies geht eleganter direkt mit

C#-Quelltext
1:
return Movie.AlternativeName ?? String.Empty;                    

(ich gehe davon aus, daß AlternativeName selber schon als 'string' deklariert ist).

Ansonsten eben

C#-Quelltext
1:
return (Movie.AlternativeName != null) Movie.AlternativeName.ToString : String.Empty;                    


P.S. Falls du den ??-Operator noch nicht kennst, s. ??-Operator [http://msdn.microsoft.com/de-de/library/ms173224.aspx]

Und noch ein P.S: Zur Vermeidung der möglichen NullReferenceException benutze ich daher ToString() nicht bei Variablen vom Typ 'String' selbst (auch wenn ich finde, daß dies der Compiler regeln bzw. eine mögliche Warnung ausgeben sollte).


greentiger - So 25.12.11 15:30

Stimmt das geht so einfach, aber so wird immernoch eine leeres Item erstellt und ausgegeben.

Habe es jetzt einmal so gelöst, bin aber für Verbesserungen offen ;)


C#-Quelltext
1:
2:
3:
4:
5:
6:
foreach (TmdbMovie element in movies)
            {               
                string film = new MovieListItem(element).ToString();
                if(film!=string.Empty)
                    listBox1.Items.Add(film);                
            }


Eidt: Da muss ich mir noch was anderes einfallen lassen, so kommt es später mit SelectedIndexChanged zu Problemen.

C#-Quelltext
1:
2:
MovieListItem listItem = (MovieListItem)listBox1.SelectedItem;
TmdbMovie movie = listItem.Movie;


Was ist daran falsch?
In der foreach Schleife soll der Wert noch gelöscht werden, wenn das Item leer ist:

C#-Quelltext
1:
listBox1.Items.Remove(string.Empty);                    


greentiger - Mo 26.12.11 14:09

Hat keiner eine Tipp für mich wie ich nur die Filme ausgeben kann ohne string.emtpy, beim Sortieren sieht das nicht gut aus, wenn am Anfang ein paar Zeilen leer sind?


Th69 - Mo 26.12.11 14:40

Hallo,

sind die Einträge auch wirklich leer (oder sind da einfach Leerzeichen drin)?
Bei letzterem einfach noch Trim() vor der Abfrage auf 'String.Empty' aufrufen bzw. ab .NET 4 mittels IsNullOrWhitespace [http://msdn.microsoft.com/de-de/library/system.string.isnullorwhitespace.aspx] überprüfen.


greentiger - Mo 26.12.11 14:55

user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:

sind die Einträge auch wirklich leer (oder sind da einfach Leerzeichen drin)?


Ja, die Einträge sind leer:
http://dl.dropbox.com/u/17888900/C%23%20empty.string.bmp


greentiger - Mo 26.12.11 16:49

Ich kann auch nicht mit listbox1.Items.Remove("filname"); ein Item löschen, es kommt aber keine Warnung/Fehlermeldung.


Yogu - Di 27.12.11 13:33

Die Frage ist doch, warum überhaupt Einträge vorhanden sind, deren Eigenschaft AlternativeName null ist. Haben die vielleicht noch eine Eigenschaft Name oder so, die dann nicht null ist? Alternative klingt so, als ob es noch einen anderen Namen geben würde.

Wenn diese Filme tatsächlich keinen Namen haben und nicht angezeigt werden sollen, dann kannst du das in dieser Schleife ganz gut lösen:

user profile icongreentiger hat folgendes geschrieben Zum zitierten Posting springen:

C#-Quelltext
 
4:
5:
6:
7:
/* ... */
            foreach (TmdbMovie element in movies)
            {                       
                listBox1.Items.Add(new MovieListItem(element));
            }

Dort kannst du noch eine if-Abfrage einbauen, die prüft, ob die Eigenschaft AlternativeName null ist, und nur im anderen Fall einen Eintrag erstellt und hinzufügt.


greentiger - Mi 28.12.11 14:06

Stimmt, es gibt Name, weiß auch nicht wie ich da auf AlternativeName gekommen bin.

Eine Kleinigkeit ist jetzt noch, viele Rückgabewerte sind "null" sowie cast, budget, genres,... wie auch hier schon einer geschrieben hat: https://themoviedbapi.codeplex.com/discussions/259649

Der Projektleiter hat in letzter Zeit 2 neue Updates herausgebracht, die in der dll noch nicht integriert sind. Der Code ist Opensource man müsste nur die jeweiligen Klassen updaten, jedoch kommt es dabei zu Problemen mit dem Verweis Microsoft.Expression.Interactions, der normal zur Verfügung stehen sollte, wenn man "Microsoft Expression Blend Software Development Kit (SDK) for Silverlight 4" installiert.

SourceCode: https://themoviedbapi.codeplex.com/releases/view/75332
Updates: https://themoviedbapi.codeplex.com/workitem/12606, https://themoviedbapi.codeplex.com/workitem/11134


Trashkid2000 - Mi 28.12.11 14:32

Naja, Du benötigst doch nur die Kalssenbibliothek, oder?
Der Fehler kommt doch aus dem Demoprojekt.

Also schmeiße doch einfach die zwei unbenötigten Projekte aus der Solution, und kompiliere dann.
Oder kompiliere halt nur die Klassenbibliothek.


greentiger - Mi 28.12.11 15:04

Beide darf ich nicht löschen aber das mit der Fehlermeldung schon, sonst kann ich es nicht mehr debuggen.

Habe jetzt TmdbMovie.cs bearbeitet und TmdbImageSize.cs neu erstellt. Aber wo muss ich jetzt die xml Dateien hinzufügen?
https://themoviedbapi.codeplex.com/workitem/11134

Bei jedem neuen Aufruf kommt jetzt noch eine Fehlermeldung:

C#-Quelltext
1:
2:
[XmlArrayAttribute("cast")]
        public TmdbCastPerson[] Cast { get; set; }

Der Typ- oder Namespacename "TmdbCastPerson" konnte nicht gefunden werden. (Fehlt eine Using-Direktive oder ein Assemblyverweis?)


Trashkid2000 - Mi 28.12.11 15:26

Einfach mal den Namespace einbinden??
Mal heißt er "TheMovieDB", und mal "TheMovieDb".


greentiger - Mi 28.12.11 17:34

Okay habe die Verweise hinzugefügt und nur noch die TmdbMovie.cs ersetzt.
Jedoch glaube ich das man die xml Dateien noch einbinden muss, jetzt werden alle abgefragten Film mit "null" zurückgegeben.

Edit: Irgendwie stimmen die Code überhautp nicht überein, beim sanitize-xml.patch sollte man die TmdbAPI.cs bearbeiten, in der ganzen Klasse findet man nichts drüber und die Klasse TmdbMovieSearchResults existiert auch nicht


greentiger - Fr 30.12.11 16:48

Danke für Eure Hilfe/Mühe ;)

Werde auf ein Update der Api warten, die Updates/fixes gehören zu einer älteren Version (1.2).

MfG greentiger


greentiger - Di 03.01.12 15:11

Habe mir jetzt den Source Code nocheinmal genau angschaut.

Und in der TheMovieDb.Example werden Converter verwendet um die Cast anzuzeigen, CastMemberConverter.cs:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
using System;
using System.Windows.Data;

namespace TheMovieDb.Example.Converters
{
    [ValueConversion(typeof(object), typeof(string))]
    public class CastMemberConverter : IValueConverter
    {
        public object Convert(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            var person = value as TmdbCastPerson;
            if (person == null)
                return "";
            string p = string.Format("{0}: {1}", person.Job, person.Name);
            if (!string.IsNullOrEmpty(person.Character))
                p += " as " + person.Character;
            return p;
        }

        public object ConvertBack(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            // we don't intend this to ever be called
            return null;
        }
    }
}

Jedoch weiß ich nicht wirklich, wie ich den Converter verwenden kann?
http://themoviedbapi.codeplex.com/SourceControl/changeset/view/84698

Ich verstehe nicht wieso mir die Genres nicht angezeigt werden, dazu wird kein Converter verwendet?

MfG greentiger


Trashkid2000 - Di 03.01.12 16:19

Hi,

naja, der Converter wird doch nur für die Oberfläche innerhalb des Bindings benötigt.
Um halt die verschiedenen Properties der Person formatiert anzuzeigen.
Aber der dürfte Dir gar nichts bringen.


greentiger - Di 03.01.12 18:19

Okay Danke, aber wie kann ich dann die Genres, Cast abfragen?

Der Rückgabetyp ist immer null:
http://dl.dropbox.com/u/17888900/C-sharp%20Forum.de%20null%20values.bmp

Wie man auf der Homepage sieht gibt es Schauspieler und Genres in der DB: http://www.themoviedb.org/movie/44982-13


Ralf Jansen - Di 03.01.12 18:54

Du verwechselst hier den Vorgang der Typumwandlung in einer Programmiersprache (Cast) mit der Filmbesetzung (Cast). Irgendeine Typumwandlung wird dir nicht helfen die Besetzungliste zu füllen. Offensichtlich ist in deinem TmdbMovie element die Cast Liste nicht gesetzt. Wie man die füllt sollte die Dokumentationen der Library hergeben. Wenn sie das nicht tut solltst du diese Library endlich in die Tonne drücken. Die ganzen Probleme die sich in diesem Thread zwischen den Zeilen auftun lassen auf ein unterirdische Qualität des (Library) Codes schließen. Wenn du nicht die Fähigkeiten hast den Code als solchen zu korrigieren (ich meine den Code der Library nicht deinen eigenen) dann solltest du die Bibliothek nicht benutzen.


Edit: Wenn du entsprechend der API Dokumentation [http://api.themoviedb.org/2.1/methods/Movie.search] der TheMovieDb Website mal das Xml oder Json für deinen konkreten Film abrufst solltest du nachsehen können ob da überhaupt Genre/Cast liefert. Ich vermute nicht sondern man wird einen zweiten Aufruf entsprechend hier [http://api.themoviedb.org/2.1/methods/Media.getInfo] durchführen müssen(wird von deiner Library scheinbar in der TmdbApi.GetMovieInfo Methode gekapselt) um bestimmte Detailinformation zu einem Film zu bekommen.


Trashkid2000 - Di 03.01.12 19:13

Hi,

also erstmal muss ich @user profile iconRalf Jansen Recht geben. Denn der Thread geht nun schon ziemlich lange, und ich finde auch, dass die Qualität der Lib nicht toll ist. Wenn es schon nicht klappt, das Spelling des Namespaces einzuhalten...

Habe mich trotzdem mal mit dem Thema auseinandergesetzt und dabei einfach mal die DemoApp verändert, kompiliert und ausgeführt. Und siehe da, klappt doch alles so, wie es soll. Die Anzeige der Genres habe ich einfach mal ganz hinten in der Liste dazugefügt. Die Solution habe ich mal hier hochgeladen.

Deinen ApiKey musst Du jeweils im MoviesViewModel und im PersonViewModel hinzufügen, an dieser Stelle:

C#-Quelltext
1:
private readonly TmdbApi _api = new TmdbApi("");                    
Hatte zum testen einfach einen genommen, den ich mit Google finden konnte :wink:
Viel Spaß damit,


greentiger - Di 03.01.12 19:24

Habe es auch gerade in der Doku gesehen, dass es keinen Wert zurückgibt. Mit Movie.getInfo bekomme ich alles zurückgeben.

Danke für Eure Hilfe, werde das Thema jetzt schließen ;)