Entwickler-Ecke

WinForms - MVC


RBS2002 - Sa 10.01.09 00:27
Titel: MVC
Hi,

ich möchte, obwohl ich wahrscheinlich keine Ahnung davon habe, ein MVC realisieren. Ich habe bisher etwas rumgeklickt und bisher nur geschafft das, dass Programm startet. Aber erst einmal der Code:

Controller:


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:
  public partial class MainForm : Form
  {
        Model model;
    public MainForm()
    {
      //
      // The InitializeComponent() call is required for Windows Forms designer support.
      //
      InitializeComponent();
      //
      // TODO: Add constructor code after the InitializeComponent() call.
      //
    }
    
    void View1MouseDown(object sender, MouseEventArgs e)
    {
      model.Add(new Grafik(e.Location, model.getDefaultTyp)); // Fehlermeldung
    }
    
    void RechteckToolStripMenuItemClick(object sender, EventArgs e)
    {
      
    }
  }
}


View:


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:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
  public partial class View : UserControl
  {
    Model model;
    
    public void setModel(Model daten)
    {
      model = daten;
      model.ModelChanged += new Model.ModelChangedHandler(OnModelChanged);
    }
    
    void OnModelChanged(object sender, EventArgs e)
    {
      this.Invalidate();
    }
    
    public View()
    {
      //
      // The InitializeComponent() call is required for Windows Forms designer support.
      //
      InitializeComponent();
      
      //
      // TODO: Add constructor code after the InitializeComponent() call.
      //
    }
    
    void ViewPaint(object sender, PaintEventArgs e)
    {
      Graphics g = e.Graphics;
      
      if(model == nullreturn;
      
      foreach(Grafik gr in model.Grafiken){
        switch(gr.Typ)
        {
          case Model.GrafikTyp.Rechteck:
            g.DrawRectangle(new Pen(Color.Black, 3),gr.DraWRect);
            break;
        }
      }
    }
  }


Model:


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:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
  [Serializable]
  public class Model
  {
        public enum GrafikTyp{
      Rechteck,
      Kreis,
      Nichts
    }
    
    public GrafikTyp DefaultTyp {
      set { defaultTyp = value; }
    }
    GrafikTyp defaultTyp = GrafikTyp.Rechteck;
    
    public GrafikTyp getDefaultTyp {
      get { return defaultTyp; }
    }
    List<Grafik> grafiken = new List<Grafik>();
    
    public List<Grafik> Grafiken {
      get { return grafiken; }
    }
    
    public bool Modified {
      get { return modified; }
    }
    
    bool modified = false;
    
    public delegate void ModelChangedHandler(object sender, EventArgs e);
    
    public event ModelChangedHandler ModelChanged;
    
    public void OnChanged(){
      modified = true;
      if(ModelChanged != null){
        ModelChanged(thisnew EventArgs());
      }
    }
    
    public void Add(Grafik grafik){
      Grafiken.Add(grafik);
      modified = true;
      OnChanged();
    }
  }


Die Fehlermeldung ist folgende:


Quelltext
1:
System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.                    


Ich schätze mal es liegt an diesem Model model; Aber da ich strikt nach meinen Vorlesungsunterlagen gehe und dort im Skript auch nichts anderes steht und bisher nichts anders funktioniert hat möchte ich das mal hier stehen lassen....

Wie gesagt, würde mich über jeden Hinweis freuen - sobald er ein Rechteck zeichnet bin ich froh :D

mfG RBS2002


UGrohne - Sa 10.01.09 08:33

Du hast recht, es liegt wahrscheinlich an model, denn das Objekt ist noch nicht erzeugt. Erzeuge es einfach mal und schaue, was dann passiert ;).


RBS2002 - Sa 10.01.09 10:43

user profile iconUGrohne hat folgendes geschrieben Zum zitierten Posting springen:
Du hast recht, es liegt wahrscheinlich an model, denn das Objekt ist noch nicht erzeugt. Erzeuge es einfach mal und schaue, was dann passiert ;).


ok, vielen Dank erstmal, mit =new Model() gehts erstmal. Jetzt kommt der Fehler zu mindestens nicht mehr, er zeichnet bisher nur noch nichts. Hast du da irgendwie noch einen nett gemeinten Ratschlag... :wink:


Kha - Sa 10.01.09 12:43

Im Controller-Konstruktor solltest du noch View.setModel aufrufen ;) .


RBS2002 - Sa 10.01.09 18:24

hmmm, okay - zeichnen will er aber immer noch nicht... Irgendwie deucht mir das bei der Grafikklasse etwas nicht stimmt.... Ist die ok wenn ich ein z.B. ein Rechteck zeichnen will oder müsste ich da auch was verändern? (sorry, habe ich irgendwie vollkommen vergessen):


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
  [Serializable]

  public class Grafik
  {
    Rectangle draWRect;
    
    public Rectangle DraWRect {
      get { return draWRect; }
    }
    Model.GrafikTyp typ = Model.GrafikTyp.Rechteck;
    
    public Model.GrafikTyp Typ {
      get { return typ; }
    }
    
    public Grafik(System.Drawing.Point e, Model.GrafikTyp typ){
      this.draWRect.Location = e;
      this.typ = typ;
    }
  }
}


Natürlich fehlt jetzt die ganze Dynamik weil ich erst einmal, zum test, alles auf Rechteck auslegen wollte. Besonders der Konstruktor sieht aus meiner Sicht komisch aus, aber irgendwie will mir keine Idee kommen wie ich daraus ein brauchbares Objekt rausziehen kann das C# das dann auch zeichnet....


Kha - Sa 10.01.09 20:29

Da du dem Rechteck keine Breite und Höhe gibts, gibt es auch nicht viel zum Zeichnen ;) .

PS: Statt

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
  public GrafikTyp DefaultTyp {
   set { defaultTyp = value; }
  }
  GrafikTyp defaultTyp = GrafikTyp.Rechteck;
    
  public GrafikTyp getDefaultTyp {
    get { return defaultTyp; }
  }

besser

C#-Quelltext
1:
2:
3:
4:
5:
  public GrafikTyp DefaultTyp {
    get { return defaultTyp; }
    set { defaultTyp = value; }
  }
  GrafikTyp defaultTyp = GrafikTyp.Rechteck;


RBS2002 - Sa 10.01.09 21:13

ok, danke für den Hinweis, habe jetzt das erstmal berücksichtigt - und, oh Überraschung - er zeichnet immer noch nicht. Jetzt glaube ich das ich das Objekt nicht richtig aufbaue und habe den Konstruktor mal so geschrieben:


C#-Quelltext
1:
2:
3:
4:
     public Grafik(System.Drawing.Point e, Model.GrafikTyp typ){
      this.typ = typ; 
      Rectangle draw = new Rectangle(e.X,e.Y,10,10);
    }


aber natürlich funktioniert auch das nicht :(


Kha - Sa 10.01.09 21:44

So wird das sicher nichts: Du stzt nur eine lokale Variable, dein draWRect-Feld bleibt aber leer.

PS: Setz doch mal einen Breakpoint in die Zeichen-Routine und schau, ob er dort überhaupt hinkommt und was für einen Wert das Rechteck hat.


RBS2002 - Sa 10.01.09 21:52

ok, danke. Das war nur ein Versuch - habe jetzt draWRect = new Rectangle(e.X,e.Y,10,10); - ist das besser? Oder soll ich das alte lassen?

Aber du hast recht, er kommt wirklich nicht bis zum Paint, also muss irgendwie, irgendwo noch ein Invalidate hin....


RBS2002 - Do 15.01.09 12:18

konnte mein Problem inzwischen selber lösen, im MainForm-Konstruktor musste noch


C#-Quelltext
1:
view1.setModel(model)                    


rein, danach hat er gezeichnet. Wo das view1 herkommt weiss ich nicht, aber naja - hauptsache es geht ;)


Kha - Do 15.01.09 16:56

*hust*
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Im Controller-Konstruktor solltest du noch View.setModel aufrufen ;) .
;) ?


RBS2002 - Do 15.01.09 17:09

du hast natürlich recht, aber ich habe ein "neues" View erstellt (also view = new View()), anstatt die feste Instanz zu nutzen die SharpDevelop für das Steuerelemt erstellt hatte. Das war, wie gesagt, im Prinzip mein Fehler.