Laden...

Forenbeiträge von Zoomy Ingesamt 22 Beiträge

25.06.2015 - 17:04 Uhr

Naja in erster Linie weil ich es nicht besser wusste 😃
Die Hinweise sind gut, ich werde mich da mal einlesen.
Danke für die Hilfe an euch beiden.

25.06.2015 - 12:51 Uhr

Hallo zusammen,

ich habe folgendes Problem und hoffe ihr könnt mir helfen:

Ich habe eine Klasse die ich mittels Serialisierung (also [Serializable()] ) in eine Datei speicher.

Nun habe ich für meine Anwendung zwei Forms die z.T. gleichzeitig geöffnet sind und beide auf die gleiche Klasse und Instanz zugreifen.
Wenn ich nun einen Wert der Klasse in der einen Form verändere, möchte ich das dieses in der anderen Klasse auch passiert.
Das haben ich mittels einem eigenen Event gemacht. Das Problem ist nur, durch den Event funktioniert die Serialisierung nicht mehr, da eine Form nicht serialisiert werden kann.

Gibt es einen Trick sich die Events zu merkern oder ähnliches? Aktuell überschreibe ich den Event dann mit null und dann ist meine Aktualisierung weg....

Hier mal ein Minimalbeispiel zum besseren Verständnis:


using System;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace WindowsFormsApplication2
{
    static class Program
    {
        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

    [Serializable()]
    public class Bsp
    {
        public string sText;

        public event EventHandler ChangeText;
        public void OnChangeText()
        {
            if (ChangeText != null)
                ChangeText(this, EventArgs.Empty);
        }

        public void Serialize(string datei)
        {
            FileStream fs = new FileStream(datei, System.IO.FileMode.OpenOrCreate);
            try
            {        
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(fs, this);
            }
            catch (Exception exp)
            { MessageBox.Show("Fehler" + exp.Message); }
            finally
            { fs.Close(); }
        }
    }

    public class Form1 : Form
    {
        private TextBox textBox1;
        private Button button1;
        private Bsp wert;

        public Form1()
        {
            textBox1 = new TextBox();
            textBox1.TextChanged += new EventHandler(this.textBox1_TextChanged);
            Controls.Add(textBox1);
            button1 = new Button();
            button1.Click += new EventHandler(this.button1_Click);
            button1.Location = new System.Drawing.Point(0, 40);
            Controls.Add(button1);
            wert = new Bsp();
            Form2 frm = new Form2(wert);
            frm.Show();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            wert.sText = textBox1.Text;
            wert.OnChangeText();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            wert.Serialize("D:\\Tausch\\tmp.data");
        }
    }

    public class Form2 : Form
    {
        private TextBox textBox1;
        private Bsp wert;

        public Form2(Bsp para)
        {
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.Controls.Add(this.textBox1);
            this.Activated += new EventHandler(Form2_Activated);
            wert = para;
            wert.ChangeText += new EventHandler(ChangeText);
        }

        private bool bChanged = false;
        private void ChangeText(object sender, EventArgs e)
        {
            bChanged = true;
        }

        private void Form2_Activated(object sender, EventArgs e)
        {
            if (bChanged)
                textBox1.Text = wert.sText;
        }
    }
}

In Wirklichkeit handelt es sich um viel mehr Daten als nur einen String, so dass ich eine grundsätzliche Aktualisierung sehr ungerne machen möchte.

Ich hoffe ihr könnt mir helfen und ein paar Tipps geben.
Vielen Dank vorab

06.11.2011 - 21:19 Uhr

Zwar etwas spät, aber vielen Dank!
Hat geklappt!

30.10.2011 - 14:11 Uhr

Hallo Forum,

ich habe ein Projekt in dem ich auf mehrere andere Projekte (Assemblys) von mir Verweise und diese dann auch verwende.

Um eine Übersicht der Versionen zu bekommen habe ich im Programm ein Infobutton eingefügt der mir Name und aktuelle Versionstand der Assemblys ausgibt.

Realisiert habe ich das wie folgt:


/// <summary>
/// Zeigt die Installierte Software an
/// </summary>
/// <param name="sender">Sender des Events</param>
/// <param name="e">Argument des Events</param>
private void mItemInstallSoftware_Click(object sender, EventArgs e)
{
    /*--- dll-Dateien die Aufgelistet werden sollen ---*/            
    string[] a_software = { "ProjektA.dll", "ProjektB.dll" , "ProjektC.dll" };

    #region "Ermitteln der Assemblyinformationen"
    //Pfad des Programms ermitteln
    string pfad = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    //Durchlaufen der Assemblys und ausgeben der Informationen
    string info = "Installierte Software:\n--------------------------\n";
    foreach (string c_software in a_software)
    {
        Assembly asm = Assembly.LoadFrom(pfad + "\\" + c_software);
        info += asm.GetName().Name + "\n" + asm.GetName().Version + "\n\n";
    }
    MessageBox.Show(info);
    #endregion
}

Nun würde ich aber auch gerne die Beschreibung und das Copyright des Assemblys, welches im VisualStudio immer angebe, gerne anzeigen lassen.
Leider habe ich bisher keine passende Klasse bzw. Methode gefunden die mir das realisiert.

Ich würde mich freuen, wenn mir jemand helfen könnte meinen Wunsch umzusetzen.
Danke im voraus!

02.07.2010 - 11:47 Uhr

Hallo,

zum ersten muss ich herbivore recht geben. Ich habe jetzt ein bisschen drüber nachgedacht und eigentlich ist das was ich mache das Austricksen der Vererbungsprinzipien. Es funktioniert zwar, weil ich sowohl die Klasse als auch die Anwendung der Klasse selber geschrieben habe und damit dir richtige verwendung sichergestellt ist, aber sollte ein zweiter mal mein Werk fortsetzen bekommt dieser damit bestimmt probleme.

Ich habe jetzt folgendes gemacht, meine Grundklassen sehen nun wie folgt aus:


  class S7_ProgrammGeneric<TBaustein, TNetzwerk>
        where TBaustein : S7_BausteinGeneric<TNetzwerk>
        where TNetzwerk : S7_Netzwerk
    {
        protected List<TBaustein> l_bausteine; 
        /* ... */ 
    }

    class S7_Programm :  
        S7_ProgrammGeneric<S7_BausteinGeneric<S7_Netzwerk>, S7_Netzwerk>
    { /* ... */ }

    class S7_BausteinGeneric<T> 
        where T : S7_Netzwerk
    {
        protected List<T> l_netzwerke;
        /* ... */ 
    }

    class S7_Baustein : S7_BausteinGeneric<S7_Netzwerk>
    { /* ... */ }

    class S7_Netzwerk
    { /* ... */ }

Die Logik der Klassen habe ich nun generisch gemacht und dort alle Member und Methoden implementiert.
Damit meine Schnittstelle zu den alten Programmen gleich bleibt (sonst müsste ich überall das Generische dazu schreiben) habe ich die Klasse S7_Programm und S7_Baustein erstellt.

Meine neuen speziellen Klassen setzen nun auf die generischen Klassen auf, ohne selber generisch zu sein.
Im Code:


    class S7_SpecialProgramm 
       : S7_ProgrammGeneric<S7_SpecialBaustein, S7_SpecialNetzwerk>
    { /* ... */ }

    class S7_SpecialBaustein : S7_BausteinGeneric<S7_SpecialNetzwerk>
    { /* ... */ }

    class S7_SpecialNetzwerk : S7_Netzwerk
    { /* ... */ }

Mit der Lösung bin ich Moment eigentlich sehr glücklich.
Meiner Meinung danach bin ich damit maximal flexibel ohne Mehrfachimplementierungen und ohne Typkonflikte
Ich hoffe das wiederspricht keinen Prinzipien? (Wenn doch dann gerne anmerken, man lernt ja immer gerne dazu)

Vielen Dank für eure Hilfe

30.06.2010 - 22:58 Uhr

Hallo Cat,

also geht um die Interpretation eines SPS-Programms, welches ich ein- und auslesen kann.
Nun ist das hier wahrscheinlich nicht so bekannt, deswegen habe ich es probiert allgemeiner zu halten.

Ich probiere es jetzt den Aufbau zu erklären.
Allgemein setzt sich das wie folgt zusammen

Programm 1 <----> n Bausteine 1 <----> n Netzwerke

Das heßt ich habe eine Klassenstruktur die mir das Programm abbildet.
Da ich aus den Erfahrungen eniger Programme festgestellt habe, je kleiner und konkreter ich ein Objekt ich in einer Klasse darstelle, desto einfach fällt es einem passende Methoden zu schreiben.

Im Code:



class S7_Programm
{
  List<S7_Baustein> l_Baustein;

  public void ReadProgramm()
  { /*...*/ }

  public List<string> WriteProgramm()
  { /*...*/ }

    //weitere Methoden und Eingeschaften
}

class S7_Baustein
{
  List<S7_Netzwerk> l_Netzwerk;

  public void ReadBaustein()
  { /*...*/ }

  public List<string> WriteBaustein()
  { /*...*/ }

    //weitere Methoden und Eingeschaften
}

class S7_Netzwerk
{
  List<string> l_sAnweisungen;

  public void ReadNetzwerk()
  { /*...*/ }

  public List<string> WriteNetzwerk()
  { /*...*/ }

    //weitere Methoden und Eingeschaften
}


Diese Klassen sind praktisch die Basis. Auf die ich aufsetzen will.
Nun habe ich einen Fall, indem ich das Programm speziell bearbeiten muss.
Aus meiner Sicht gibt es drei Möglichkeiten die Beabeitungen in die Klassen zu bekommen:

  1. Die bestehenden Klassen erweitern.
    -> Da Allerdings das Assembly und der Namespace völlig unterschiedlich ist, ist dieses praktisch nicht möglich und macht auch keinen Sinn weil die Bearbeitung wirklich etwas neues und spezielles ist.
  2. Die Bearbeitung in einer extra Klasse zu machen und alles neues Außerhalb der Klassenstruktur umzusetzen.
    Allerdings müsste ich dann viele protected Member public machen um auf alle benötigten Member zugreifen zu können.
    -> Möglich aber doch sehr sehr umsauber und die einfache Struktur ist nicht mehr einfach.
  3. Meine Idee der Ableitung.
    Meiner Meinung nach die sauberste und einfachste Lösung. Einziges Problem ist die Typunstimmigkeiten in den Listen.

Wenn ich zu den Typproblemen noch eine schöne Lösung finde, dann könnte ich wunderbar alle neuen Bearbeitungen umsetzen.

30.06.2010 - 15:27 Uhr

Hallo Cat,

danke für die schnelle Antwort. Das mit der generisch Klasse habe ich auch schon überlegt, aber die Typwandlungen fallen dann ja nicht weg. Ich weiß in erster Linie dann doch nur, dass T vom Typ IB ist.
Aber alle Methoden und Eigenschaften die in der Vererbungslinie weiter unterliegen muss ich doch dann durch erstmals Typprüfung von T und Typkonvertierung in die entsprechende Klasse wandeln.
Oder gibt es einen anderen trick?

30.06.2010 - 14:09 Uhr

Hallo Forum,

ich hab ein Frage zum Aufbau meiner Klassen. Um meine Frage klären zu können muss ich etwas ausholen und mein Aufbau erklären:

Ich habe folgenden Fall, eine Klasse A1 beinhaltet n mal die Klasse B1.
Gelöst habe ich das, in dem ich in der Klasse A1 eine Liste von B1-Klassen angelegt habe.
Im Code sieht das dann (natürlich start vereinfacht) so aus:



class A1
{
  protected string sName;
  protected List<B1> l_B1;  //Liste der Klasse B1
 
  public A1()
  { l_B1 = new List<B1>(); }

  public string Name
  {
     get{ return sName; }
     set{ sName = value; }
  }

  public string BKlassenName(int index)
  {return l_B1[index].Name; }
}

class B1
{
  protected string sName;
 
  public B1()
  {}

  public string Name
  {
     get{ return sName; }
     set{ sName = value; }
  }
  
}

Das Funktioniert auch soweit wunderbar und so stelle ich häufig Objekte dar, die beliebig oft andere Objekte beinhalten.

Nun muss ich aber an einer Stelle das Konzept erweitern. Das heißt jeder Klasse muss ein paar Eigenschaften dazu bekommen. (ohne dabei die ursprünglichen Klassen zu verändern)
Der erste Gedanke ist, die Klasse A2a wird von der Klasse A1 abgeleitet und die Klasse B2a wird von der Klasse B1 abgeleitet.
Das ganze sieht dann so aus:



class A2a : A1
{
  protected List<B2a> l_B2a;  //<- Macht keinen Sinn, da ja bereits l_B1 geerbt wird
 
  public A2a()
  { }

  public string BKlassenWert(int index)
  {
      return ((B2a)l_B1[index]).Wert;  //<- Benötigt immer die Typkonvertierung
  }
}

class B2a : B1
{
  protected string sWert;
 
  public B2a()
  {}

  public string Wert
  {
     get{ return sWert; }
     set{ sWert = value; }
  }
  
}

Was mich nun stört ist, dass wenn ich auf meine ursprüngliche Liste zurückgreifen will, immer erst den Typ in Klasse B2a konvertieren muss.
In dem Beispiel geht es noch, allerdings bei komplexerer Methoden wird das schnell unübersichtlich und man kommt durcheinander mit den unterschiedlichen Typen und Konvertierungen (Es soll später auch noch die Klasse A2b und A2c geben. die beide von A1 erben, sowie die Klassen B2b und B2c)
Eine neue Liste in der Klasse A2a zu erstellen macht aber noch weniger Sinn, da man ja bereits die alte Liste (inkl. Methoden) hat.

Ich suche nun nach einer deutlich sauberen Lösung. Hat vielleicht jemand von euch eine Idee, wie ich meinen Aufbau verbessern kann?
Würde mich über eine Antwort freuen!

12.06.2010 - 20:14 Uhr

Also DockPanel Suite finde ich ganz hervorragend für dass, was ich machen will.
Vielen Dank für die Hilfe.

12.06.2010 - 17:02 Uhr

Ja stimmt das habe ich wirklich jetzt häufiger gesehen.

Gibt es dafür auch ein Fachbegriff, damit ich auch über dieses Programmierkonzept informieren kann?
Dann kann ich das zu meinem Projekt besser passende Konzept umsetzen.

12.06.2010 - 16:52 Uhr

Ja genau sowas habe ich gesucht, vielen Dank!

Nun kommt gleich bei der goole Suche das Openbook indem steht:
"MDI-Fähigkeiten (Multiple Document Interface) waren bis vor wenigen Jahren der Standard bei allen Anwendungen, die mehrere gleichartige Dokumente verwalteten. Denken Sie nur an die älteren Versionen von Microsoft Word oder Microsoft Excel, die vielleicht bekanntesten MDI-Vertreter."

Nun würde mich ja interessieren, was aktuell der Standard ist.

12.06.2010 - 16:23 Uhr

Hallo Forum!

Ich möchte ein Windows-Programm schreiben, in dem kleine weitere Programme enthalten sind.
Ich stelle mir das ähnlich zu Office Produkten so vor, dass ich ein Hauptfenster habe und in diesem weitere Fenster aufrufen kann. Diese Fenster können dann minimiert, maximiert und geschlossen werden und passen sich auf das Hauptfenster an.

Ich nenne dieses "Fenster in Fenster" Anwendung, kenne den richtigen Namen aber nicht, so dass ich keine Suchtreffer finde.

Geht so etwas?
Ob das nun in Windows.Forms oder WPF geschrieben wird ist mir gleich. Hauptsache die Funktionalität wird erfüllt.

Würde mich freuen wenn mir jemand Helfen könnte.

27.07.2009 - 14:48 Uhr

Ok ich habe es jetzt schon befürchtet.

Danke für eure Hilfe...

27.07.2009 - 14:45 Uhr

Ich habe mir jetzt den Hook angeschaut und festgestellt, das es nicht sonderlich schwer ist. Problem ist nur, dass wenn ich die Buttons "JA" "NEIN" "ALLE" "KEINE" haben will, ich vier Buttons umbennenen müsste. Leider gibt es aber bei MessageBoxButtons nur Kombinationen mit maximal drei Buttons. Wie bekomme ich da den jetzt noch den vierten Button hinein.

27.07.2009 - 14:35 Uhr

@herbivore
du hast natürlich recht.
Ich bin bloß nicht weiter gekommen als:


public class MyMessageBox : MessageBox
{ }

Dann kam bereits eine Fehlermeldung mit der ich nicht umgehen konnte:
"Für den Typ "System.Windows.Forms.MessageBox" sind keine Konstruktoren definiert."

@gfoidl
D.h. die erste Möglichkeit die du vorschlägst ist, einfach ein Formular nachbauen, oder?
Dann muss ich aber die Vielzahl an Möglichkeiten der MessageBox entweder auch nachbauen muss oder ich verzichte auf die Vielzahl.
Die zweite Möglichkeit sieht auf den ersten Blick sehr kompliziert aus. Ich werde sie mir jetzt aber mal näher anschauen.
Vielen Dank erstmal für die Hilfe!

27.07.2009 - 13:24 Uhr

Hallo Forum!

Ich benutze immer mal wieder MessageBoxen für Fragen an den Benutzer.
Leider Vermisse ich die Button-Kombination "JA" "NEIN" "ALLE" "KEINE".

Nun wollte ich die gerne selber nachflegen in dem ich eine Klasse MyMessageBox schreibe, die dann die Funktionen von MessageBox überschreibt.

Leider krieg ich da gar nichts hin...

Hat jemand vlt eine Idee wie ich eigene MessageBoxButtons erstellen kann.

Würde mich über Hilfe sehr freuen.

11.02.2009 - 16:27 Uhr

Hallo!

Hab eure Beiträge erst jetzt gesehen.

@kleines_eichhoernchen:
Nach dem Hinweis von GMLOD habe ich das so umgeschrieben. Habt ihr beide recht, das ist schöner.

@zommi
Mit dem Cast hast vollkommen recht. Ist mir vorher nicht aufgefallen.
Und wenn ich konsequent bin, muss ich den Typparameter auch groß schreiben.
Auch wenn "T" in der Literatur üblich ist, hab ich mich jetzt für "Typ" entschieden, weil ich es einfach noch lesbarer finde.
(P.S. übrigens schicker name;) und auch ich komme ursprünglich aus Berlin)

Danke euch beiden!

Mein Code sieht nun mittlerweile so aus:


public class FabisAlgorithmen 
{
    public static void BubbleSort<Typ>(Typ[] feld) where Typ : IComparable
    {
         int nr = 1;
         bool sort;
         Typ tmp;
         do
         {
             sort = true;
             for (int i = 0; i < feld.Length - nr; i++)
             {
                 if (feld[i].CompareTo(feld[i + 1]) > 0)
                 {
                     sort = false;
                     tmp = feld[i + 1];
                     feld[i + 1] = feld[i];
                     feld[i] = tmp;
                 }
             }
             nr++;
        } while (!sort);
}

Übrigens will ich noch ein großes Lob an euch alle aussprechen. Im programmieren bin ich recht fit, allerdings programmier ich noch nicht sehr lange in .NET.
Und kenn deswegen viele Möglichkeiten noch nicht. Ihr habt mir alle geholfen ein bisschen besser hinterzusteigen;-)

08.02.2009 - 12:42 Uhr

Ja die Methode habe ich auch kennengelernt, als ich nach dem Interface ICloneable gesucht habe.
Mir ging es auch mehr um andere Algorithmen als den Bubblesort. Der hat sich bloß als Anfangsbeispiel angeboten, weil man den nun schon einige male in verschiedenen Sprachen programmiert hat.

Dank eurer Hilfe habe ich aber wirklich einiges gelernt, also hat es sich aufjedenfall gelohnt, vielen dank nochmal 😉

08.02.2009 - 12:33 Uhr

Stimmt, das ist noch viel besser!

Das war dass, was Andavos schon am Anfang meinte, ich bloß nicht richtig verstanden habe, bzw. aus unwissenheit nicht umgesetzt habe.

Viel Dank an alle!

08.02.2009 - 12:12 Uhr

Hallo!

Nach dem ich es gestern noch ausprobiert habe, will ich heute noch meine funktionsfähige Lösung präsentieren.
Ob das nun die beste Lösung ist, weiß ich nicht. Ich hätte eigentlich lieber die Methode anstatt der Klasse als generic, aber so funktioniert es erstmal 😉


public class FabisAlgorithmen<typ> : IComparable<typ>
{
        
    int IComparable<typ>.CompareTo(typ t)
    {
        return ((IComparable)this).CompareTo(t);
    }

    public static void BubbleSort(typ[] feld)
    {
         int nr =1;
         bool sort;
         typ tmp;
         do
         {
             sort = true;
             for (int i = 0; i < feld.Length - nr; i++)
             {
                 if (((IComparable)feld[i]).CompareTo(feld[i + 1])>0)
                 {
                     sort = false;
                     tmp = feld[i + 1];
                     feld[i + 1] = feld[i];
                     feld[i] = tmp;
                 }
              }
              nr++;
          } while (!sort);
     }
}

Sollte jemand noch einen Verbesserungsvorschlag haben, bin ich für alles offen.
Ansonsten hoffe ich, das es vlt jemanden den noch weiter hilft, den im Internet habe ich sonst zu dem Thema nicht alt so viel gefunden.

Einen schönen Sonntag an alle!

07.02.2009 - 12:31 Uhr

Wow das ging ja echt schnell.
Ich werd es mal versuchen. Vielen dank!

07.02.2009 - 11:48 Uhr

Hallo Forum!

Ich programmiere mittlerweile auf Arbeit eine Menge und stelle immer wieder fest, das man den ein oder anderen Algorithmus, den man im Studium gelernt hat auch dort wieder verwenden kann.
Nun hab ich gedacht, ich schreibe mir eine Klasse, die diese Algorithmen umfasst.
Ich wollte genauso schön einfach, wie im Studium auch, zunächst mit dem Bubblesort anfangen.
Damit er nicht Typen abhängig ist, habe ich gedacht ich schreibe ihn mit einem generic.
Das ganze sieht dann so aus:


public static void BubbleSort<typ>(typ[] feld)
{
    int nr =0;
    bool sort;
    typ tmp;
    do
    {
        sort = true;
        for (int i = 0; i < feld.Length - nr; i++)
        {
            if (feld[i] > feld[i + 1])                          //<- Fehler
            {
                sort = false;
                tmp = feld[i + 1];
                feld[i + 1] = feld[i];
                feld[i] = tmp;
             }
         }
         nr++;
    } while (!sort);
}

Nun habe ich festgestellt, das beim größer Vergleich ein Fehler auftritt.
Der Operator ">" kann nicht auf Operanden vom Typ "typ" und "typ" angewendet werden.
Kann mir da jemand helfen, das zu umgehen?

Würde mich sehr freuen. Besten dank schon mal.