none
VS2010Prof,C#,Projektstart RRS feed

  • Frage

  • Hallo,

    ich habe eine vielleicht wieder typische Anfängerfrage:

    Es gibt eine Projektmappe, in der befinden sich zB. 2 Projekte : Pro1 und Pro2

    Kann man durch einen Click auf einen Button eines Forms in Pro1 das Projekt Pro2 starten, in diesem einen Job erledigen,  und von dort wieder durch einen Click auf einen Button eines Forms in Pro2 zum Ausgangsform Form1 in Pro1 zurück kehren ?

    Vielen Dank !

    Hermann

    Sonntag, 4. Juli 2010 10:35

Antworten

  • Hallo Hermann,

    präzisieren solltest Du: Was für ein Job soll dort von Projekt zwei erledigt werden.

    Wenn die zwei Projekte Windows/Konsolen/WPF-Anwendungensprojekte sind,
    wären es zwei unterschiedliche Anwendungen,  und dort gibt es zunächst keinen
    automatischen Datenaustausch.
    Den müsstest Du folglich programmieren, sei es in Form einer Dateiübergabe
    oder anderer Art der Prozesskommunikation.
    Starten kannst Du ein anderes Programm (ob das VS Projekte sind, ist dabei
    sekundär) durch Process.Start

    Einfacher könnte aber sein, ein Projekt (z. B. Projekt 2) als Klassenbibliothek
    zu gestalten und in das erste Projekt einzubinden.
    Inwieweit das sinnvoll ist, hängt von meiner Eingangsfrage ab.

    Gruß Elmar

     

    Montag, 5. Juli 2010 07:23

Alle Antworten

  • Hallo Hermann,

    präzisieren solltest Du: Was für ein Job soll dort von Projekt zwei erledigt werden.

    Wenn die zwei Projekte Windows/Konsolen/WPF-Anwendungensprojekte sind,
    wären es zwei unterschiedliche Anwendungen,  und dort gibt es zunächst keinen
    automatischen Datenaustausch.
    Den müsstest Du folglich programmieren, sei es in Form einer Dateiübergabe
    oder anderer Art der Prozesskommunikation.
    Starten kannst Du ein anderes Programm (ob das VS Projekte sind, ist dabei
    sekundär) durch Process.Start

    Einfacher könnte aber sein, ein Projekt (z. B. Projekt 2) als Klassenbibliothek
    zu gestalten und in das erste Projekt einzubinden.
    Inwieweit das sinnvoll ist, hängt von meiner Eingangsfrage ab.

    Gruß Elmar

     

    Montag, 5. Juli 2010 07:23
  • Hallo Elmar,

    meine Frage wurde aus der Not geboren! Wie Du weißt, habe ich mir VS2010Pro zugelegt, vorallem auch um endlich ein gutes Werkzeug zum Drucken von Datenbankinhalten zu haben. Das geht auch wirklich wunderbar, aber nur solange die Programme für sich alleine sind. Ich habe mich aber zu früh gefreut ! In dem Augenblich, indem ich versuche, diese in ein Projekt einzubinden, geht nichts mehr. Einbinden heißt: Ich habe es Struktur -und wortident genau nach Anweisung in meinem Projekt neu erstellt.

    Beispiel:

    Ich habe mir ein Übungsprogramm Pro1 (GebTag) zum Erfassen, Editieren und Löschen von Einträgen von Geburtsdaten in eine Datenbank (PuTag.mdb) geschrieben. Jetzt wollte ich die erfassten Datensätze in einer Liste ausdrucken. Dazu habe ich zuerst ein weiteres Übungsprogramm Pro2 mit VS2010Pro und den darin enthaltenem Reporting Services nur zum Drucken des Datenbankinhaltes geschrieben. Das funktioniert wunderbar. Ich habe  daher Pro2 genauso wie Erstellt ins Programm Pro1 eingefügt - leider kommt immer irgend eine Fehlermeldung !

    Pro2 habe ich nach MS Doberenz/Gewinnus  -Datenbankprogrammierung mit Visual C# 2008 (Seite 575)- erstellt. Geht einfach und schnell und macht was man sich wünscht. Eingefügt in Pro1 liefert es allerdings immer irgend einen Fehler:

    Habe in Pro1 ein Form1 mit einem Button1 und rufe damit FormDruck in Pro1 auf. (Dieses habe ich wie gefordert mit Report, Reportviewer usw. erstellt). In diesem findet sich die Methode -Load.

    private void FormDruck_Load(object sender, EventArgs e)
        {
           this.PuTagTableAdapter.Fill(this.PuTagDataSet.PuTag);   // Zeile 1
           this.reportViewer1.RefreshReport();
        }

    Das wäre die einfachste Lösung gewesen. Aber Zeile 1 zeigt den Fehler: Die ConnectionString-Eigenschaft wurde nicht initialisiert. Ersetze ich hier aber Zeile 1 durch Zeile 2 (siehe weiter unten), erhalte das gleiche Ergebnis wie folgt:

    Im Projekt ist natürlich alles enthalten: ConnectionString, DataAdapter, BindingSource, PuTagDataSet usw. Das Pro1 greift natürlich mehrfach auf die immer gleiche Datenbank PuTag.mdb zu, auch die Methode FormDruck. Vermutlich liegt hier das Problem. Ich bringe den Fehler einfach nicht weg. Habe daher einen anderen Weg aus dem MS Buch (Seite 582) versucht:

    private void FormDruck_Load(object sender, EventArgs e)
        {
          PuTagDataSet puDS = new PuTagDataSet();
          BindingSource puBS = new BindingSource();
          puBS.DataSource = puDS;
          puBS.DataMember = "PuTag";
          ReportDataSource rds1 = new ReportDataSource();
          rds1.Value = puBS;
          reportViewer1.LocalReport.DataSources.Add(rds1);
          reportViewer1.LocalReport.ReportEmbeddedResource = "GebTag.PuReport.rdlc";  // Zeile 2
           this.reportViewer1.RefreshReport();
        }

    Dieser Weg zeigt überraschend wenigstens das zu druckende Formular, mit Kopf -und Fußzeilen, aber ohne Inhalt, also keine Textzeilen !! Beim Erstellen von Pro1 werden alle Datenverbindungseigenschaften für das UPDATE, DELETE, INSERT, DataView  usw. definiert, ich vermute aber, daß diese nicht für das (Pro2 -) FormDruck passen.

    Jedenfalls hatte ich die Idee, die gut funktionierenden DruckModule einfach als Ganzes in die Projektmappe von Pro1 zu kopieren und von Pro1 aus aufzurufen, um eine Lösung zu haben. Daß Dir das nicht gefällt verstehe ich gut, mir auch nicht, aber was soll ich tun ?

    Viele Grüße !

    Hermann

    Dienstag, 6. Juli 2010 10:30
  • Hallo Hermann,

    aus der Not werden Tugenden geboren!
    Visual Studio bringt alles dazu mit, um auch komplexe Projekte in Griff zu bekommen.

    Generell empfiehlt sich größere Anwendungen in mehrere Projekte aufzuteilen,
    das erhöht die Wartbarkeit und erleichtert das Testen uam.
    Visual Studio unterscheidet generell mehrere Projekt/Ausgabetypen,
    was man bei der Erstellung bzw. in den Projekt-Eigenschaften unter
    Seite "Anwendung", Projekt-Designer (C#)
    Interessant ist zunächst der Ausgabetyp , wobei die Windowsanwendung
    oder Klassenbibliothek für Dich die beiden interessanten sind.

    So solltest Du ein Hauptprojekt als Windows Forms (oder WPF) Anwendung erstellen,
    was man üblicherweise bereits durch die Auswahl bei der Projekt-Erstellung tut.
    Alle weiteren Projekte wären Klassenbibliotheken, die Du später der Hauptanwendung
    als abhänigiges Projekt (über Projekt->Projektabhängigkeiten hinzufügst.

    Desweiteren findest Du in den Projekt-Anwendungs-Eigenschaften den Standardnamespace .
    Darüber kannst Du eine Organisation der Klassen für Deine Belange festlegen.
    Dabei empfiehlt (Pflicht ist es nicht) sich eine Organisation nach dem Schema
    <Firmenname>.<Anwendung/Projekt>.<Bereich>, z. B.:

    • HermannSbg.ErstesProjekt.Formulare
    • HermannSbg.ErstesProjekt.Berichte
    • HermannSbg.ErstesProjekt.Datenzugriff

    Wobei eine weitere / tiefere Schachtelung je nach Anforderung möglich ist,
    man es dabei nicht übertreiben sollte.
    Beachten solltest Du auch, das es sich dabei um eine logische Trennung handelt,
    d. h. ein Namespace kann in unterschiedlichen Projekten wiederholt werden.

    Mehr dazu findest Du u. a. Namen von Namespaces
    Dort findest Du weitere Richtlinien, wie Entwerfen für Erweiterbarkeit
    auf die ich jetzt nicht eingehe, um dies hier nicht zu einem Roman werden zu lassen ;-)

    Du solltest eine entsprechende die Trennung vornehmen und Deine Formular
    in ein Projekt und Deine Bericht in das zweite. Ein drittes empfihelt sich für den
    gemeinsamen Datenzugriff (z. B. DataSet/TableAdapter wie Dein PuTagDataSet),
    soweit sie gemeinsam genutzt werden. 
    Dabei sollte es keine Überkreuzverweise geben, sondern nur eine Richtung für Abhängigkeiten.

    Nach dieser langen Vorrede zu Deinem Projekt:
    Damit nun Dein Bericht die gleichen Daten verwendet wie das Formular,
    mußt Du das verwendete DataSet übergeben. Was hier besser als die BindingSource
    ist, da ein Report die Filterung durch eine BindingSource nicht berücksichtigen kann.

    Gemeinsame Dinge wie die Verbindungszeichenfolge steuerst Du über die Einstellungen
    des Hauptprojekts und weist sie entsprechend zu.

    Ich hoffe, das Ganze kommt einigermaßen verständlich rüber -  ansonsten nachhaken!

    Gruß Elmar
    Dienstag, 6. Juli 2010 14:36
  • Hallo Elmar,

    dein Hinweis auf Process.Start war ein voller Erfolg. Ich habe dies in die betroffenen Projekte eingebaut und kann nun jeweils das zugehörige Druckprogramm durch Button-Click auf einem Form des Hauptprogrammes oder durch einen Doppelclick auf den Icon des Druckprogrammes am Bildschirm starten.

    Jedenfalls ist das Problem Drucken eines gesamten Inhalts einer Datenbank gelöst und vom Tisch !

    Dafür vielen Dank !

    Gruß Hermann

    Dienstag, 13. Juli 2010 07:07
  • Hallo Elmar,

    deine letzten Hinweise haben mir eine völlig andere Einsicht zur Organisation von Projekten gebracht. Ich habe einige Tage in den Links herumgelesen, möchte aber zuerst noch mein aktuelles Projekt = Problemfall zu Ende bringen: Das Drucken von einer zur Laufzeit erstellen Auswahl von Datensätzen. Dieses Thema frustriert mich nämlich langsam (Meine Frage vom 6.7.2010).

    - Es gibt eine Datenbank PuTag.mdb

    - aus dieser selektiere ich mit SELECT nach frei - ua. auch aus einer Listbox- wählbaren Kriterien Datensätze

    - diese schreibe ich mit da.Fill(dt) in eine DataTable dt

    - diese dt übergebe ich einem datagridView zu Anzeige des Ergebnisses

    - ist das OK, soll die Auswahl gedruckt werden

    - dazu schreibe ich die Auswahl gleich auch in ein DataSet ds mit da.Fill(ds)

    - dieses übergebe ich einer Methode: printList auf einem Form: PrintForm. Auf diesem finden sich auch der Report PuReport.rdlc und der ReportViewer reportViewer1.

    public void printList(DataSet ds)  // übernimmt das dataSet, kann ich überprüfen - es ist da

    {

    Welche Codezeilen gehören hier her ?? Der Debugger zeigt mir überall das übergebene DataSet, aber derReportViewer bekommt anscheinend die Sache nicht mit !

    ??

    reportViewer1.LocalReport. ..  ??? ....; 
    this.reportViewer1.RefreshReport();

    }

    Mein Gefühl sagt mir, daß nur wenige Infos notwendig sind, um die Daten dem Viewer zu übergeben, aber es will einfach nicht gelingen ! Er zeigt mir max. das gesamte Layout mit Kopf- und Fußzeilen usw. aber ohne den Textteil, also keine Textzeilen. Ich habe alles mögliche versucht - umsonst. Was kapiere ich hier wieder einmal nicht ?

    Du sagst mir, ich soll das erstellte DataSet übergeben - aber wie ?

    Vielen dank !

    Hermann

    Dienstag, 13. Juli 2010 07:59
  • Hallo Hermann,

     

    Damit der Bericht die Daten zu sehen bekommt, mußt Du Sie der DataSources
    Auflistung hinzufügen. Gezeigt wird das bei der LocalReport-Klasse , wo die Zeile

    lr.DataSources.Add(new ReportDataSource("Sales", GetSalesData()));
    
    

    die Daten abruft und dem Bericht zuweist.
    Anstatt einer Methode (oben GetSalesData) kannst Du die DataTable
    aus dem Dataset (ds) direkt zuordnen.
    Wobei der Aufbau in der Struktur mit der in dem Bericht verwendeten
    Beschreibung übereinstimmen muß. Und damit der Berichtsdefinition
    mit dem angegebenen Namen zugewiesen wird.

    Mehrere Abrufe für die gleichen Daten - da.Fill(ds), da.Fill(dt) -
    sind im allgemeinen nicht notwendig und blähen nur den Speicher auf.

    Gruß Elmar

    Dienstag, 13. Juli 2010 08:35
  • Hallo Elmar,

    bitte um Nachsicht, wenn ich schon wieder komme, aber wenn es wieder nicht klappt, lasse ich die Sache liegen und gehe in  den Urlaub !

    Ich habe gemacht, was Du vorgeschlagen hast:

     private void FormPrint_Load(object sender, EventArgs e)
        {
          Microsoft.Reporting.WinForms.LocalReport lr = new
               Microsoft.Reporting.WinForms.LocalReport();
          lr.ReportPath = "PrintReport.rdlc";
          lr.DataSources.Add(new ReportDataSource("PrintReport",this.dt4));
          //this.BookTableTableAdapter.Fill(this.BookListeDataSet1.BookTable); //  --> Problem !
          this.reportViewer1.RefreshReport();
        }

    Mit dem Debugger kann ich verifizieren, daß dt4 richtig übernommen wurde, in lr unter DataSource: Name = PrintReport, Value = BookListe (=Name der Datenbank) und darin die Auswahl dt4 richtig vorhanden ist.

    Das Problem liegt also in der Zeile //  --> Problem! Angezeigt wird nämlich der leere Report, also der ohne Textzeilen. Im Entwurf für den Report habe ich eingestellt:

    FormPrint-Entwurf: Berichtsdatenquelle : DataSet1 und
    Datenquelleninstanz: BookTableBindingSource

    Bitte nochmals um Nachsicht und um Hilfe, aber diese Kleinigkeit laugt mich aus !

    Danke !

    Gruß Hermann

    Mittwoch, 14. Juli 2010 19:16
  • Hallo Hermann,

    zunächst muß der Name der ReportDataSource (oben "PrintReport") identisch
    sein mit dem Namen den Du beim Entwurf des Berichts als Datenquelle angegeben hast.

    Und als Parameter muß Du die DataTable übergeben, die im Aufbau der Datenquelle
    enspricht und die anzuzeigenden Daten enthält.

    Oben übergibst Du für die ReportDataSource nun this.dt4 .
    Willst Du aber die BookTable anzeigen wie das "Problem" vermuten lässt,
    so sollte der Code eher lauten:

      this.BookTableTableAdapter.Fill(this.BookListeDataSet1.BookTable); 
      lr.DataSources.Add(new ReportDataSource("PrintReport", this.BookListeDataSet1.BookTable));
       
    

    Wird es nun gar nichts, so geniesse zunächst Deinen Urlaub,
    und gehe danach mit frischen Kräften und etwas Abstand neu ans Werk.

    Gruß Elmar

     

    Donnerstag, 15. Juli 2010 08:37
  • Hallo Elmar,

    ich habe es geschafft ! Und zwar auf eine "watscheneinfache" und völlig simple Art! In der MS-Literatur hatte ich die beiden Zeilen gefunden, die der Assistent beim Verbinden des reportViewers mit der Datenquelle automatisch anlegt :

    this.BookTableTableAdapter.Fill(this.BookListeDataSet1.BookTable);
    this.reportViewer1.RefreshReport();

     

    Damit wird der gesamte Inhalt der Datenquelle angezeigt. Ich kam auf die Idee, einfach den DataAdapter durch den von mir im SELECT - Command definierten Adapter da4 zu ersetzen. Das wars !! Wie und was immer an Datensätzen ausgewählt wird, kommt damit als genaues Abbild in den reportViewer zum Drucken !

    this.da4.Fill(this.BookListeDataSet1.BookTable);
    this.reportViewer1.RefreshReport();

    Damit ist auch dieses Problem vom Tisch. Eine allgemeine Frage dazu hätte ich allerdings noch an dich: Ich habe ein MS-Buch mit einem Kapitel über Reporting Services, allerdings für C#2008. Jetzt arbeite ich mit VS2010 Pro und dem darin entahltenen C#2010. Für mich überraschend ist die Tatsache, daß der Umfang an Methoden für den reportViewer 2010 deutlich geringer (und auch umständlicher zu bedienen) ist gegenüber dem von 2008! So kann man zB. in 2010  keine Tabellen (bei kurzen Feldinhalten) platzsparend in mehreren Spalten nebeneinander anordnen usw. Habe ich hier etwas falsch gemacht ? Ich werde dazu noch eine Frage an MSDN stellen, Zb. auch wie man einen string zum Drucken in einer Kopf- oder Fußzeile an den viewer übergeben kann.

    Wieder vielen Dank für deine Hinweise und deine Geduld mit mir !

    Gruß !

    Hermann

     

    Samstag, 24. Juli 2010 10:36