Laden...
Avatar #avatar-2316.jpg
JuyJuka myCSharp.de - Experte
Fachinformatiker: Anwendungsentwicklung Deutschland Dabei seit 30.11.2005 2.187 Beiträge
Benutzerbeschreibung
Ich liebe OO und vor allem OOD. Mit Klassen, Interfaces, Assoziaitonen, Vererbung, Kapselung, Patterns und und und verbring ich meine Arbeits- und meine Freizeit. *stahl*

Forenbeiträge von JuyJuka Ingesamt 2.187 Beiträge

20.06.2009 - 13:31 Uhr

Hallo bonzy,

Es gibt eine Lösugn: Raus aus Dispose.
Die Methode Dispose ist fest im interface System.IDisposable definiert:

Führt anwendungsspezifische Aufgaben durch, die mit der Freigabe, der Zurückgabe oder dem Zurücksetzen von nicht verwalteten Ressourcen zusammenhängen.

Du musst/solltest also eine andere Methode finden in der du deine Aufgaben erledigen kannst, z.B. kannst du dich an das Closing-Event der übergeordneten Form hängen (FindForm()) oder ähnliches.

Gruß
Juy Juka

18.06.2009 - 11:09 Uhr

Hi,

Es fehlt einfach noch ein BindingFlags:

BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance

Gruß
Juy Juka

17.06.2009 - 07:50 Uhr

Hallo Voidcore,

wenn du selber eine "Lösung" gefunden hast, schreib diese bitte als neuen Post in den Thread, damit das "Unbeantwortet"-Kennzeichen verschwindet. (Was sich jetzt mit diesem Post erledigt hat.)

Gruß
Juy Juka

16.06.2009 - 13:51 Uhr

Hallo punkdevil,

[System.ComponentModel.TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]

Über das aufzuklappende Property oder die Klasse die (wenn als Property verwendet) aufgeklappt werden soll und fertig ist es.

Gruß
Juy Juka

16.06.2009 - 13:36 Uhr

Hallo andrgrau,

herbivor hat hier recht. Das Projekt zu kopieren und zu ändern ist nicht sehr sinnvoll.

Die GUI kann man (im einfachsten fall) als UserControl implementieren, welches von der eigentlichen Form (aus dem Basis-Projekt) geladen und angezeigt wird.

Und das mit "nur einer exe" lässt sich
A) über .Netz lösen, welches mehrer Assemblies zu einerm zusammen paken kann.
B) oder man vewirft es einfach, da für das Ausführen einer .Net-Anwendung eh das gesamte Framework installiert sein muss (d.h. mit nur der *.exe kommt man egal wie man es dreth nicht besonders weit.

Ach ja: Wilkommen auf mycsharp.de!

Gruß
Juy Juka

16.06.2009 - 10:51 Uhr

Hallo @All,

So detailiert kann man nur im Sequenzdiagramm sein, siehe Anhang.
Aber selbst das ist keine 100%ige beschreibung von foreach.

Gruß
Juy Juka

15.06.2009 - 22:26 Uhr

Hallo ehochipi,

wilkommen auf mycsharp.de .
Habs zwar nicht getestet, es müsste aber wie folgt gehen:


typeof(MyClass).GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);

Gruß
Juy Juka

15.06.2009 - 14:15 Uhr

Hallo Mega,

willkommena auf mycsharp.de.

Mit welcher Fehlermeldung stürtz dein Programm ab?
Auf welche Framework-Version hast du deine Anwendung compiliert?

Gruß
Juy Juka

15.06.2009 - 13:24 Uhr

Hallo klines_eichhoernchen,

Bei privaten, nicht-signierten Assemblies (shared, nicht-signiert gibt's ja nicht) muss eine Assembly nicht neu-compiliert werden, wenn eine referenzierte Assembly in einer neuen Version vorliegt.

Das referenzierte Assembly wird nur mittels des "friendly Names" geladen, der weder Versions- noch Sprachinformationen enthält. Es findet standardmäßig keine Versionskontrolle stadt.

In VisualStudio findet man die entsprechende Einstellung, wenn man auf das referenzierte Assembly (also unter "Verweise"/"Referenzes") klickt und die Eigentschaften (F4) aufruft, es heißt "Spezifische Version" (keine Ahnung wie auf Englisch).

Gruß
Juy Juka

15.06.2009 - 09:21 Uhr

Hallo,

events sind eine Umsetzung des Observer Pattern/Observer(Entwurfsmuster), nur dass man hier stadt eines ganzen interfaces einzelne lose Methoden verwenden kann.

Delegaten werden nicht nur für events verwendet sondern können beliebig dazu verwendet werden Methoden zu übergeben, das (meiner Meinung nach) einfachste Beispiel ist ein Bubble-Sort:


public void bubbleSort( IList<int> liste ) 
{
  for(int i = liste.Count;i>decimal.Zero;i--)
  {
    for(int i2 = (int)decimal.Zero;i2<(i-decimal.One);i2++)
    {
      int i2plus = i2+(int)decimal.One;
      if(liste[i2]>liste[i2plus]) // nur diese eine Zeile ist spezifisch für int, ...
      {
        int zwi = liste[i2];
        liste[i2]=liste[i2plus];
        liste[i2plus] = zwi;
      }
    }
  }
}

Nur diese eine Zeile ist spezifisch für int, wäre doch schön diese austauschen zu können ... Und so kann man diese mittels Delegat austauschen:


public void bubbleSort( IList<T> liste, Comparer<T> comparer ) 
{
  for(int i = liste.Count;i>decimal.Zero;i--)
  {
    for(int i2 = (int)decimal.Zero;i2<(i-decimal.One);i2++)
    {
      int i2plus = i2+(int)decimal.One;
      if(comparer(liste[i2],liste[i2plus])>decimal.Zero) // comparer gibt 0, 1 oder -1 zurück je nach dem welches Objekt größer ist
      {
        T zwi = liste[i2];
        liste[i2]=liste[i2plus];
        liste[i2plus] = zwi;
      }
    }
  }
}

Gruß
Juy Juka

15.06.2009 - 08:43 Uhr

Hallo,

Wollte mir auch mal den Webcast ansehen aber es läd bei mir beim besten willen nicht runter! Gibt's da irgend eine andere Quelle wo man es laden kann?

Gruß
Juy Juka

12.06.2009 - 20:01 Uhr

Hallo Itrader,

Für private Assemblies:
Man muss System.AppDomain.CurrentDomain.AssemblyLoad abonieren und dort einfach den übergebenen string umwandeln (Split auf , und damit laden).
Alternativ kann man auch einfach nur mit dem AssemblyNamen laden ohne Version, Clutur, usw. (z.B. einfach nur "MyAssemblyName" stadt deinem Beispiel)

Für globale Assemblies:
Für private Assemblies kann man dem neuen Assemblie (der neuen Version) eine Publischer-Policity mitgeben siche auch :rtfm:.

Gruß
Juy Juka

12.06.2009 - 13:44 Uhr

Hallo sl3dg3hamm3r,

Ich habe jetzt nur deinen Post gelesen (nicht die Artikel) aber deine groben Aussage stimme ich vollkommen zu.
ADO.NET ist gut wenn es um Datenbankzugriffe geht, aber sobald man die Daten hat sollte man sofort ADO.NET hinter sich lassen.

ADO.NET hat zwei große Nachteile

  1. Keine Interfaces
    Man kann mit DataTables bzw. dem Designer für typisierte DataTables keine Interfaces impementieren.
  2. Keine Logik-Schicht
    Das standard Vorgehen von ADO.NET sieht keine Logik-Schicht vor, es wird alles direkt in der Form gemacht.

Das Problem, das man "jeden Fizzel" bei Objekten selber Programmieren muss kann und sollte man sich durch ein Framework vom Hals schaffen, ich persönlich kenne das Entity Framework auch nicht, aber was man so an Beispiel-Code im Netz sieht ist und was man so liest ist es gut. (Auch zu nennen wäre natürlich NHibernate und wenn du die Forensuche bemühst kommen noch einige andere Frameworks zu Tage.)

Gruß
Juy Juka

12.06.2009 - 11:49 Uhr

Hallo DaMoe80,

Es handelt sich um ein halbes Missverständniss. Ich hab das "alle" in Anführungszeichen gesetzt, da man eigentlich nie alle möglichen Testfälle abprüfen kann. Und meinen tu ich mit "alle": Alle Testfälle die im momentanen Entwurfszustand bekannt sind.
Wo bei man hier zwischen Entwurf und Implementation unterscheiden muss. Der Entwurf ist/sollte immer das gesammte System sein, dass auch (theoretisch) Funktioniert.

Gruß
Juy Juka

12.06.2009 - 08:41 Uhr

Hallo Jelly,

Das Problem gibt es nur mit Signierten Assemblies.

Gruß
Juy Juka

12.06.2009 - 08:29 Uhr

Hallo #coder#,

Zu erst erstellt man ein Design und definiert so die Signatur aller Methoden (besser gesagt die Signatur von allem was man entwickelt, Klassen, Methoden, Assemblies, etc.) und das zu erwartende Ergebniss.

Wenn man diese Angaben hat kann man die Unit-Tests dazu schreiben, ohne vorher die zu testenden Dinge entwickelt zu haben.

Die erste Frage hast du dir ja selbst behandelt. Nur muss man eben drauf achten erst "alle" Unit-Tests für einen Komponente (Assembly, Klasse, ...) geschrieben zu haben bevor man anfängt diese zu Entwicklen.

Gruß
Juy Juka

05.06.2009 - 10:20 Uhr

Hallo Hero,

Das Problem ist, dass du nur ein ListViewItem erzeugst, stadt für jede DLL ein neues.
Falsch:

ListViewItem lv = new ListViewItem();
foreach (string dll in files)
{
  string df = Path.GetFileName(dll);

Richtig:


foreach (string dll in files)
{
  ListViewItem lv = new ListViewItem();
  string df = Path.GetFileName(dll);

Gruß
Juy Juka

04.06.2009 - 22:36 Uhr

Hallo chanderegg,

Da gibt es mehrer möglichkeiten:

  1. Überschreibe ToString der "eingebundenen" Entity-Klassen (sehr unsauberer lösung)
  2. Implementiere IFormatable und gibt über DataGridView->Columns->[die Spalte]->DefaultCellStyle->Format den Parameter dafür an (besser als nur ToString überschreiben, aber immer noch nicht 100%ig).
  3. Besorg dir eine bessere BindingSource, mit der du auch auf Properties von "eingebundenen" Objekten zugreifen kannst (das ist DIE Lösung, jedoch hab ich auch noch keine brauchbare BindingSource für diesen Fall gefunden).
  4. Aboniere das CellFormating-Event des DataGridView, ca. so:

private void DataGridView_CellFormation(object sender, CellFormatingEventArgs e)
{
  if(e!=null&&e.ColumnIndex == this.DataGridView.Columns.IndexOf(this.aufgabeDataGridViewTextBoxColumn))
  {
    IAufgabe aufgabe = e.Value as IAufgabe;
    if(aufgabe!=null)
    {
      e.Value = ...; // hier das aufgabe-objekt auslesen und einen String daraus erstellen.
      e.FormatingAppliede = true;
    }
  }
}

Gruß
Juy Juka

04.06.2009 - 15:10 Uhr

Hallo muecke,

schau dir einfach mal die definition von Escape-Sequenz an. Sollte alle Fragen beantworten.

Gruß
Juy Juka

04.06.2009 - 10:06 Uhr

Hallo,

Das W finde ich gut. Wikipedia verwendet es ja auch als Icon (im IE wird es vor der URL und in den Favoriten angezeigt). Eventuell könnte man noch einen weißen Hintergrund machen wie beim original Icon.

Gruß
Juy Juka

04.06.2009 - 09:33 Uhr

Hallo mychewie,

Willkommen auf mycsharp.de

Für sowas gibt es XQuery, womit ich mich aber nicht auskenne.

Eventuell kannst du uns aber das Problem auch mal etwas genauer beshchreiben. Hast du ein Schema für das XML? Was gibt es alles für Möglichkeiten (also was darf der Benutzer alles abfragen)?

Gruß
Juy Juka

03.06.2009 - 16:30 Uhr

Hallo SeeQuark,

Danke, genau den hatte ich gesucht.

Gruß
Juy Juka

03.06.2009 - 16:28 Uhr

Hallo Hans0001,

Willkommen auf mycsharp.de 😃

Das mit den Panels war schon ein guter Ansatz. Du kannst die Pannels auch übereinander legen, stadt in einander. Dann funktioniert es so wie du willst.
(irgend wo im Forum gibt's auch einen Thread dazu such)

Gruß
Juy Juka

03.06.2009 - 14:04 Uhr

Hallo @All,

An dieser Stelle sollte man SOFORT die ComboBox vergessen.
Hier mal der StandardCode aus unserer Firma:


// Da null nicht gebunden werden kann definieren wir uns eine ersatz "Konstante"
private readonly [TypDerGebundenIst] _Null[TypDerGebundenIst] = new [TypDerGebundenIst]();

public virtual [TypDerGebundenIst] Selecte[TypDerGebundenIst]
{
  get
  { 
    // Wir geben den ausgewählen Wert zurück wobei wir null zurück geben falls es sich um die Konstante handelt
    [TypDerGebundeIst] re = this.bindingSource.Current as [TypDerGebundenIst];
    if(re==this._Null[TypDerGebundenIst])
      re = null;
    return re;
  }
  set
  {
    // wir wählen den übergebenen Wert aus, wobei wir null gegen die Konstante austauschen und eine Exception werfen falls der Wert nicht ausgewählt werden kann.
    int index = this.bindingSource.IndexOf(value??this._Null[TypDerGebundenIst]);
    if(index<=decimal.Zero)
      throw new ArgumentOutOfRangeException("value");
    this.bindingSource.Position = index;
  }
}

public IEnumerable<[TypDerGebundenIst]> [TypDerGebundenIst]List
{
  // Wir geben alle Werte aus der Auswahl zurück
  get{return this.bindingSource.DataSource as IEnumerable<[TypDerGebundenIst]>; }
  set
  {
    // wir erstellen eine Auswahl aus der übergebenen Liste, wobei wir null gegen die Konstante austauschen (da null ja nicht gebunden werden kann)
    BindingList<[TypDerGebundenIst]> zwi = new BindingList<[TypDerGebundenIst]> ();
    foreach([TypDerGebundenIst] instanz in value??new [TypDerGebundenIst][]{/*Hier standardwerte einfügen */})
    {
      zwi.Add(instanz??this._Null[TypDerGebundenIst]);
    }
    this.bindingSource.DataSource = zwi;
  }
}

private void Form_Load(object sender, EventArgs e)
{
  this.[TypDerGebundenIst]List = null; // initalisiert die standard Werte
}

Mit diesem Code kann man alle nötigen Operationen ausführen ohne auf die Combobox zuzugreifen.
Ausgewählten Eintrag hohlen: value = this.Selected[TypDerGebundenIst];
Eintrag auswählen: this.Selected[TypDerGebundenIst] = value;
Mögliche Auswahlen in die Liste eintragen: this.[TypDerGebundenIst]Liste = values;
Mögliche Auswahlen aus Standard setzen: this.[TypDerGebundenIst]Liste = null;
Mögliche Auswahlen auslesen: values = this.[TypDerGebundenIst]Lise;

Gruß
Juy Juka

03.06.2009 - 12:25 Uhr

Hi Edward,

Immer wider gerne. grins und weit aushohl

Gruß
Juy Juka

03.06.2009 - 12:12 Uhr

Hallo Edward,

Alle deine Vermutungen und dein Vorgehen sind korrekt.
Die fehlende Zeile Code bei dir ist im Konstruktor der Form oder im Form_Load-EventHandler:

this.produktlisteBEBindingSource.DataSource = meineInstanzVonProduktlisteBE;

Gruß
Juy Juka

02.06.2009 - 17:38 Uhr

Hallo bluedragon,

dann erklär ich es mal, aber nur weil ich gute Laune habe 😁 :


[CSHARP](c1==null?null:c1.Nick)[/CSHARP]
Der Teil ist schnell erklärt (und kommt auch noch zwei mal vor): Ich nehme einfach den Nick von einerm Chatter-Objekt (c1 oder c2) falls dieses nicht [color]null[/color] ist ansonsten [color]null[/color].
Also bleibt von der Sortierung noch folgendes übrig:
[CSHARP]chatter.Sort(delegate(Chatter c1, Chatter c2){return string.Compare([Nick von c1],[Nick von c2]);}); [/CSHARP]


[CSHARP]string.Compare(...)[/CSHARP]
Das kann man sogar in der MSDN nachlesen, die Methode ermittelt einfach nur den Unterschied zwischen zwei [color]string[/color]-Objekten und giebt diesen (als Zahlenwert) zurück.
Also bleibt von der Sortierung noch folgendes übrig:
[CSHARP]chatter.Sort(delegate(Chatter c1, Chatter c2){return [Unterschied zwischen Nick von c1 und c2 als Zahl];}); [/CSHARP]


[CSHARP]delegate(Chatter c1, Chatter c2){...}[/CSHARP]
Dies ist ein Anonymer Delegat, als eine ganz normale Methode, die man auch so hätte schreiben können:
[CSHARP]public static decimal Compare(Chatter c1, Chatter c2)
{...}[/CSHARP]
Also bleibt von der Sortierung noch folgendes übrig:
[CSHARP]chatter.Sort(Compare);[/CSHARP]


[CSHARP]chatter.Sort(...)[/CSHARP]
Das kann man jetzt wirklich in der MSDN schauen. Im Endefeckt sortiert es, mit hilfe der Compare-Methode.

Gruß
Juy Juka

01.06.2009 - 16:45 Uhr

Hallo bluedragon,

Ja:

  • Ja, die Frage ist "dumm" (bitte Anfürhungszeichen beachten), da auch die MSDN eine Antwort liefern würde.
  • Ja, ne extra Liste ist blösinn.

Lösung:


chatter.Sort(delegate(Chatter c1, Chatter c2){return string.Compare((c1==null?null:c1.Nick),(c2==null?null:c2.Nick));});

Grüße
Juy Juka

31.05.2009 - 09:31 Uhr

Hallo hafi80,

Wenn die Komponente kein interface zur Verfügung stellt kannst du doch "einfach"* selbst ein interface definieren und mittels Adapter-Muster die fremde Komponente einbinden.
Wie "einfach" hängt natürlich von der größe der Komponente ab.

Gruß
Juy Juka

29.05.2009 - 21:08 Uhr

Hallo dt2158,

Es ist ja auch nur ein Beispiel. Man braucht nur das System.Type-Objekt (nicht ein Objekt der Klasse) um Reflektion zu verwenden.
Da kommt mit typeof ran:


Type stringType = typeof(string);
// oder
public class GenericKlass<T>{
Type type = typeof(T);
}
// oder 
public virtual void GenericMethod<T>{
Type type = typeof(T);
}
// oder 
Type typeObjektDerKlasse = instanzVonDerKlasse.GetType();

Gruß
Juy Juka

29.05.2009 - 21:04 Uhr

Hallo Schamese,

bei uns/mir hat es auch ohne xml-Namespace funktioniert.
Aber hauptsache es geht bei dir auch und das mit dem xml-Namespace hilft bestimmt jemandem mal weiter.

Gruß
Juy Juka

29.05.2009 - 19:40 Uhr

Hallo Shamese,

In der App.config folgendes eintragen:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding>
      <probing privatePath=".\bin" />
    </assemblyBinding>
  </runtime>
</configuration> 

Wäre auch hier zu finden gewesen Pfad zu Verweis dynamisch angeben

Gruß
Juy Juka

29.05.2009 - 19:32 Uhr

Hallo antoschka,

Das ganze per Observer-Pattern zu lösen ist möglich.
Dazu solltest du deine List<> gegen eine BindingList<> oder ObservableList<> (ka, wie die genau heißt, benutze .Net2.0) austauschen, da diese ein Event auslöst wenn ein Element entfernt oder hinzugefügt wird. Dann muss die Klasse in der Auflistung noch INotifyPropertyChanged implementieren. So kannst du die Liste sicher überwachen.

Gegen die Lösung mit dem Find ist aber auch okey, man sollte es halt noch optimieren.

  • keine Delegaten
  • sortierte List<> oder ein Dictionary<,> mit dem Type-String als Key.

Gruß
Juy Juka

27.05.2009 - 18:08 Uhr

Hallo Zebes,

Alle Zustände die nicht innerhalb einer Methode behandelt werden können müssen mit einer Exception die Methode verlassen. (<Punkt)

Öm wer schreibt das vor? Hast du irgend eine Referenz die das begründet empfielt? Würde mich mal interessieren, wie dort mit Exceptions umgegangen wird. Zu Exceptionhandling hatte ich mir mal vor einiger Zeit ein paar Sachen durchgelesen. Und dort hies es (ich müsste das jetzt selbst erst wieder raussuchen) das man eine wirkliche Ausnahme von z.B. einer Fehleingabe unterscheiden soll und es eine Frage der Interpretation und des Konzeptes ist ab wann man eine Exception verwendet.

Als Beispiel wurde dort die Division durch 0 genannt. Ist das eine Ausnahme, dass ein Benutzer sowas eingibt? Auf Benutzerebne würde ich dafür keine Exception werfen. In einer Schicht der Infrastruktur schon eher.

Da braucht man nun wirklich keine Referenzen zu. Das ist doch aus der Natur der Sache klar, oder?

Beispiel: Wenn eine Methode durch läufen wird einen Barcode(Byte-Folge) generiert der die Artikelnummer enthalten soll, die Artikelnummer aber nicht eingetragen wurde, was kann diese Methode dann noch groß machen? => Exception

Das würde mit jeder definition einer Methode so laufen. Die gesamte Anwendung verhält sich natürlich anders (Eingaben werden z.B. validiert und nicht direkt blind verarbeitet). Aber innerhalb einer Methode ist es eben zu Ende und man kann nur noch mit einer Exception aussteigen.

Kommt aber natürlich alles auf die Methodendefinition an. Das beste Beispile hier ist immer Parse und TryParse:
Für Pares ist definiert, dass es den übergebenen Parameter umwandelt, wenn dies nicht möglich ist, kann die Methode sich nicht beenden.
Bei TryParse ist definiert, dass die Methode den Wert umwandelt oder einen Standardwert zurück gibt. Hier kann die Methode weiter arbeiten, da es ja einen für den Fall der Fälle den Standardwert gibt.

Zurück zum Beispile: Wenn anstelle der Artikelnummer auch der Primärschlüssel im Barcode ausgegeben werden kann, dann muss man keine Exception werfen sondern kann die Methode korrekt beenden. 😉

Ach ja, um auf dein Devide-By-Zero-Beispiel einzugehen: Die /-Methode kann per definition nichts mit einer 0 als Divisor anfangen. Ein Eventhander, der die /-Methode aufruft kann es aber per Definition, er kann den Benutzer Warnen und das (nicht existente) Ergebnis einfach nicht anzeigen. Was soll die /-Methode da machen? Was soll sie als Ergebnis zurück geben, nämlich nichts zurück geben geht nicht ( 😉 Exceptions mal ausen vor) ?

Wenn ich unsere Texte jetzt so 2-3 mal gelesen habe sagen wir ja im Endefekt das gleiche. 😁 Nicht?

Gruß
Juy Juka

26.05.2009 - 22:57 Uhr

Hallo @All,

FZelle hat etwas interesantes gepostet:
Macht ein DataSet zum schnellen Flitern von Buisness-Objekten Sinn?

Ich werd's mal ausprobieren.

Weitere Implementationen immer noch willkommen.

Gruß
Juy Juka

26.05.2009 - 22:41 Uhr

Hallo herbivore,

Delegaten sind schon eine geniale Lösung (hab ich ja auch gleich gesagt).
Jedoch muss man auch bei Delegaten einen Typ kennen, nämlich den Delegat-Typ. Und wenn men es "klassisch" löst kennen Funktions- und Präsentationsschicht beide das interface.

ABER ich sage nicht, das man über interfaces gehen soll. Events/Delegaten sind eine geniale Lösung. Ich wollte nur ausdrücken, dass es im Endeffekt genauso funktioniert und die Präsentationsschicht sich selbst der Funktionsschicht bekannt* macht.

Gruß
Juy Juka

* Bekannt machen, aber nur Indirekt über eine implementierte Schnittstelle (ein Delegat oder ein (interface

26.05.2009 - 19:40 Uhr

Hallo herbivore,

Dies ist eine der seltenen Gelegenheiten wo ich mal wiedersprechen muss.
Bei Events wird der Empfänger auch mit übergeben (Delegate._Target oder so) und Events sind auch nur eine (besonders gute) Implementation des Observer-Patterns, welches man normal auch/oder speziell mit interfaces implementiert.

[EDIT]

Event Dekleration


public delegate void EventHandler(object sender, EventArgs e);

public class EventSender
{
  public event EventHandler DasEvent;

  public void OnDasEvent(EventArgs e)
  {
    EventHandler x = this.DasEvent;
    if(x!=null) x(this,e);
  }
}

Event Abonoment


eventSenderInstanz.DasEvent += new EventHandler(eventSenderInstanz_DasEvent);

interface Dekleration


public interface IEventHandler
{
 void Methode(object sender, EventArgs e);
}

public class EventSender
{
  private List<IEventHandler> _DasEvent = new List<IEventHandler>();

  public void AddDasEvent(IEventHandler neu)
  {
    if(neu!=null&&!this._DasEvent.Contains(neu))
      this._DasEvent.Add(neu);
  }

  public void RemoveDasEvent(IEventHandler alt)
  {
    if(this._DasEvent.Contains(alt))
      this._DasEvent.Remove(alt);
  }

  public void OnDasEvent(EventArgs e)
  {
    List<IEventHandler> x = new List<IEventHandler>(this.DasEvent);
    if(x!=null) 
      foreach(IEventHandler xx in x)
        xx.Methode(this,e);
  }
}

interface Abonoment


... class ... : IEventHandler
{
  ...
  eventSenderInstanz.AddDasEvent(this);
  ...
}

[/EDIT]

Gruß
Juy Juka

26.05.2009 - 18:43 Uhr

Hallo Zebes,

Ob ich nun Events feuer oder eine entsprechende Methode aufrufe ist eigentlich egal.

Im großen und ganzen ja. In C# gibt es aber eben genau dafür Events, darum Events.

Also hier sollte man erst mal klären was die Businessschicht ist. Wäre das bei MVP das Model?

Bin mit MVP nicht so bewandert, würde aber sagen, dass die Regeln auf alle Schichten angewendet werden können und somit für Model und View gelten (Presenter ist ja die "oberste" Schicht und von daher ist es nur hier unwichtig).

Das jede Fehleingabe mit eine Exception enden muss halte ich persönlich für Blödsinn. Ist aber an der Stelle aber auch davon abhängig, was man als Exception ansieht. Eine fehlende Resource wie z.B. Netzwerk wäre eine Ausnahme. Bei Fehleingaben sehe ich das aber nicht so.

Alle Zustände die nicht innerhalb einer Methode behandelt werden können müssen mit einer Exception die Methode verlassen. (<Punkt)

Gruß
Juy Juka

26.05.2009 - 13:39 Uhr

Hallo,

Wenn in der Business-Logik.Schicht ein Fehler auftritt, wie gebe ich dann die Fehlermeldung an die GUI-Schicht weiter? Ich meine jetzt nicht nur Exceptions,
z.B. "Sie haben in die Textbox nichts eingegeben! "
oder
"Ihre Änderungen wurden gespeichert!"
oder
"Zu Ihrer Suche wurden keine Kunden gefunden."

Jeder Fehler in der Business-Schicht muss mit einer Exception enden! Das z.B. kein Text eingegeben ist würde man mit einer ArgumentException beantworten (die UI würde nur den Text austauschen, damit der Benutzer blickt was faul ist).
Die Anderen Meldungen sind ganz normale Rückgabe werte der Methoden, die man abprüfen und anzeigen würde (in der UI). (Da hat eveN recht.)

Ist es sinnvoll, die Methoden in der Business-Schciht statisch zu machen,
damit man nicht jedes Mal, ein Objekt der Klasse erzeugen muss?

Grundsätzlich erst mal: "Nein".
Es gibt immer Außnahmen, diese sind aber so extrem selten, dass man das getrost unter den Tisch fallen lassen kann.
Wenn du glaubst alle Methoden der Business-Schicht statisch machen zu können ist es anzunehemn, dass da ein grober Fehler im Design ist oder du schlimmsten falls Objektorientierung falsch verstanden hast.

O.K. Aber auch Typprüfungen (z.B. ist die Eingabe ein Integer)? Oder wäre das dann schon ein Fall für die Business-Schicht?

Falls die Typenumwandlung in der UI-Schicht notwendig ist (z.B. Integer in einer TextBox) dann muss das die UI machen. Die Bussiness-Schicht sollte immer die "richtigen" DatenTypen verwenden. Man sollte nie Daten in einem anderen DatenTyp speichern als normal, d.h. z.B. Datumsangaben immer als System.DataTime nie als System.String und Zahlen immer als System.Int32, System.Int16, etc. und nicht als System.Byte[], Bilder als Image-Objekte und nicht als System.Object, etc. (dies gilt z.B. auch für eigene Business-Objekte auf die man Verweise in einem Business-Objekt hält, da wird auch nciht der "Primärschlüssel" als Property-Verwendet sondern das Objekt selbst).

@Zebes: Das würde man nicht so machen. Die Business-Schicht solle ehr Event's feuern worauf dann die UI reagiert (eben mit MessageBoxen oder irgend was anderem).

Im allgemeinen kann ich nur DataBinding empfehlen, da gibt es schon alle benötigten Mechanissmen von Microsoft vor gefertigt:

  • INotifyPropertyChanged
  • BindingSource
  • ErrorProvider
  • System.ComponentModel
  • etc.

Gruß
Juy Juka

26.05.2009 - 08:54 Uhr

Hallo Bad_Hoschi,

Der ErrorProvider zeigt auch Ausnahmen an, die wärend des Bindens auftreten.
Da her funktioniert z.B. auch folgendes Property völlig korrekt beim Binden:


public string Name
{
  get{return this._Name;}
  set
  {
    if(value==null)
      throw new ArgumentNullException("value"); // wird vom ErrorProvider angezeigt
    if(value==string.Empty)
      throw new ArgumentExceptio("value"); // wird vom ErrorProvider angezeigt
    this.VerursachePropertyChanged("Name", ref this._Name, ref value);
  }
}

Dadurch kann man ein standard Verhalten implementieren, das gleichzeitig mit DataBinding und normalen Code-Zugriff funktioniert, ohne irgend welche komischen Fehlerstati (z.B. mit IDataErrorInfo) rum zu reichen, die beim Programmieren (also wenn man per Code zugreift) probleme machen. (Kann man auch in den Richtlinen für die Entwicklung von Klassenbibliotheken nach sehen, dass fehler immer mit einer Exception zu behandeln sind.)

Gruß
Juy Juka

26.05.2009 - 08:50 Uhr

Hallo float,

Willkommen auf mycsharp.de 🙂

Die Ausnahme hat erst mal nichts mit der ToolStripComboBox zu tun sondern mit deinem EventHandler. Du greifst auf toolStripComboBox1.SelectedItem zu ohne zu prüfen ob es null enthält.
Da du eh den Text brachst kannst du entweder über SelectedText gehen oder stadt ToString() folgendes machen:

string.Empty + toolStripComboBox1.SelectedItem

Das mit dem verzögerten Anzeigen kann ich mir jetzt nicht erklären.

Schon mal die Richtlinien für die Benennung gesehen? Kann ich dir nur empfehlen. toolStripComboBox1 ist nicht so toll, besser wäre tabellenNameToolStripComboBox.
Außerdem solltest du dir sofort this angewöhnen, das ist viel besser lesbar.

Gruß
Juy Juka

26.05.2009 - 08:43 Uhr

Hallo Bad_Hoshi,

... da der Controller erst mit der BindingSource verknüpft wird, wenn die Daten schon geladen sind.

Zufall. So bald dein Controller noch wo anders eingesetzt wird kann sich das ändern. (Und eventuell bist nicht mal du der jenige, der den Controller dort verwendet.) Lieber gleich sauber INotifyPropertyChanged implementieren und gut ist.

Kannst du dein Problem eigentlich auch nachstellen, also in einem kleinen Test-Projekt oder so?
Hast du mal versucht einen ErrorProvider auf der Form zu Plazieren und mit der BindingSource zu verknüpfen? (Dadurch kommt man an die Fehlermeldungen)
Kannst du uns das fehlerhafte Projekt (oder die nachgestellte Variante) hochspielen?

Gruß
Juy Juka

25.05.2009 - 16:48 Uhr

Hallo lousek,

Die Events sind nur ein Hilfsmittel der Objektorientierung.
Grob gesagt geht es bei Objektorientierung darum
A) Dinge der Realenwelt direkt im Programm abzubilden (z.B. ist ein Auto in einem Rennspiel ein Objekt, genau wie in der realen Welt).
B) Informationen zu Kapseln (also z.B. das Auto-Objekt kann dir sagen, ob es los fahren kann (auto.KannFahren()), was das Auto jetzt alles prüfen muss um true zurück zu geben ist "außen" völlig egal, es ist weg gekapselt).

Übertragen auf das Schachspiel:
A) Objekte ermitteln (z.B. scharzer Spiler1, weißer Spiler, Schachbrett, schwarzer Bauer 1, weiße Dame 1, etc.)
B) Ermitteln was die Einzelnen Objekte kapseln (z.B. Schabrett weiß Laenge und Breite, schwarzer Bauer 1 weiß seine Position und dass er immer nur einen Schritt nach vorn machen darf, etc.)

Das ist jetzt nur ein Vorschlag, man könnte es auch ganz anders aufteilen.

(Achtung! hier war/ist noch keine GUI mit drinen, die gibt's noch mal extra und diese wiedrum Kapselt wie die ganzen Objekte auf dem Bildschirm dargestellt werden.)

Als einfachsten Anfang kann ich dir Empfehlen das ganze einfach als Text aufzuschreiben (also wie man Schach spielt) oder so einen Text aus dem INet zu suchen und dann eine Dokumentenanalyse zu machen:

  1. Alle Nomen werden zu Objekten
  2. Alle Verben werden zu Methoden
  3. Die Methoden den Objekten zuordnen (m zu n)
  4. Die Objekte zusammen fassen zu Gruppen (=Klassen)

und schon hat man ein halbwegs brauchbares Klassenmodel, dass man auch besprechn könnte.

Gruß
Juy Juka

25.05.2009 - 15:50 Uhr

Hallo ErfinderDesRades,

ja, vlt.. Aber Bad_Hoshi tauscht ja den ganzen Controller aus. Was ist das überhaupt für ein Objekt, welches SetController() aufruft - tauscht der Controller sich selber aus?

Der Controller darf/soll/kann sich nicht selbst austauschen, da er ja keine Ahnung haben soll wo er benutzt wird. Das muss ein anderer Controller der übergeordnet ist tun, z.B. wenn man eine Such-Maske und eine Eine-Instanz-Maske hat, tauscht der Controller der Such-Maske den Controller der Eine-Instanz-Maske aus.
Oder wenn eine Maske unter zwei Menü-Punkten des Hauptmenüs der Anwendung auftauchen soll, mit je einem anderen Controller, tut dies der Controller des Hauptmenüs.

(Aber ein ViewModel würde auch nicht komplett ausgetauscht, glaubich.)

Da muss ich passen 🙁 , mehr als von der Existenz von MVVM und der groben Theorie weiß ich nicht. Leider.

Gruß
Juy Juka

([EDIT]Ich will die Smilies wieder standardmäßig aktiv haben. X [EDIT]

25.05.2009 - 13:28 Uhr

Hallo,

Das mit dem Clear() und anschließendem Add() mache ich, weil die Instanz des Controllers eine andere sein kann und durch ResetBindings ja nur die Daten des zuvor hinzugefügten Controllers neu geladen werden würden und nicht die des neuen.
So verstehe ich Databinding aber nicht, daß man da die Bussiness-Schicht komplett auswechselt.
Die Daten wechseln, die Objekte bleiben.

Ich mach das genauso wie Bad_Hoshi. Die Daten sind ja im Normalfall das Objekt und warum sollte ich es dann nicht komplett austauschen? Warum muss ich den Zustand meines Objektes komplett umbauen und riskieren, dass der Zustand "falsch" wird? Bei manchen meiner Business-Objekte kann ich das überhaupt nicht, da Sie selbst schreibgeschützt sind. Was mach man dann?
Also aus meiner Sicht ist das komplette austauschen des Objektes die korrekte Vorgehensweise (auch wenn ich nachfolgenden Code besser finde als Clear und Add).

bindingSource.DataSourch = new MeineKlasse[]{meineInstanz};
// löst alle benötigten Ereignisse aus und aktuallisiert alle gebundenen Steuerelemente. 

Ich finde den MVC-Pattern in WinForms iwie komisch (um nicht zu sagen: unbrauchbar), weil man Controller und View ja gar nicht trennen kann, weil der View besteht ja aus Controls, und die sind aktiv, und kannste denen auch nicht abgewöhnen, ist ja auch kein Zufall, dass die Controls heißen.

Da hat ErfinderDesRades apsolut recht, das MVC-Pattern stammt noch aus Zeiten von Shells und Consolenanwendungen. Es ist bei GUI's hoffnungslos veraltet. Neuere Muster (die ich kenne) sind MVP und MVVM, aber ein "gescheites" Pattern hab ich noch nicht gefunden. (Irgend wo im Forum hab ich auch einen Thread zu dem Thema geöffnet, weiß aber nicht mehr wo.)

Gruß
Juy Juka

25.05.2009 - 13:13 Uhr

Hallo Bad_Hoschi,

Vielleicht hilft es dir das DataBinding mal von der Anderenseite - dem Model also - auf zu ziehen.

Wenn sich das Modell ändert sieht der StackTrace im groben wie folgt aus:


Model.set_MeinProperty(value="neuer Wert")
Model.OnPropertyChanged(propertyName="MeinProperty")
...

Das alles Passiert in dem Thread, der MeinProperty aufruft.

Wenn das ganze jetzt DatenGebunden ist geht der StackTrace so (als Beispiel eine TextBox):


Model.set_MeinProperty(value="neuer Wert")
Model.OnPropertyChanged(propertyName="MeinProperty")
BindingSource.Current_PropertyChanged(...)
BindingSource.OnPropertyChanged(propertyName="Current")
Binding.Target_PropertyChanged(...)
Binding.PushData(...)
Model.get_MeinProperty()
TextBox.set_Text(value="neuer Wert") 

Und das alles immer noch im Thread der uhrsprünglich "set_MeinProperty" aufgerufen hat. Allso kracht es in der letzeten Zeile, da auf TextBox.Text ohne Invoke aus irgend einem Thread zugegriffen wird.

Ich hoffe herbivores Aussage

...darf der Zugriff auf diese Objekte nur noch aus dem GUI-Thread erfolgen. ist damit einleuchtender.

Gruß
Juy Juka

25.05.2009 - 05:16 Uhr

Hallo ErfinderDesRades,

Es ist schon schön kurz aber man muss bedenken, das der Code schon ziemlich ekelhaft ist (zumindest so lange es keinen propertyof-Operator gibt).

Gruß
Juy Juka

24.05.2009 - 16:22 Uhr

Hallo ErfinderDesRades,

... im DesignerCode.InitializeComponents() steht, dann kann man im Form-Designer die Databindings einstellen, das ist, wennman vielen Controls hat, bestimmt eine ziemliche Erleichterung.

ROFL!! Erleichterung? Das ist der einzige Grund warum man DataBinding überhaupt benutzt! Sonst könnte man ja eh alles per Code hin und her schieben, da dieser Code besser aussieht als der Datebinding-Code!
*grinst extrem breit*
Das mit dem Designer hatte ich dir auch schon in einem anderen Thread erzählt.

Ich lache übrigens nicht über dich, sondern über die Absurdität von DataBinding, wenn es keine Designer-Unterstützung hätte. Ohne Designer ist nämlich der DataBinding-Code so schauder Schrecklich, dass man lieber alles selber codieren sollte.

Gruß
Juy Juka

24.05.2009 - 16:15 Uhr

Hallo lord_fritte,

das Modul kann man "nur" in eine .Net-Anwendung innerhalb des IIS einbinden, und dort über die web.config.


  <system.web>
    <httpModules>
      <add name="[AssemlbyQualifiedName]"
           type="[AssemlbyQualifiedName]"
           />
    </httpModules>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
      <add name="[AssemlbyQualifiedName]"
           type="[AssemlbyQualifiedName]"
           />
    </modules>
  </system.webServer>

Welche der beiden Sections vom jeweiligen IIS unterstütz werden kann man nur schwer ermitteln, einfach einzeln und Kombiniert ausgeben (ich glabue mit der obigen Kombination hat man die größte warscheinlichketi).

Debuggen geht ganz einfach in dem man A) das ganze in VS mit F5 startet oder B) sich per "An Prozess anfügen" an "w3w.exe" (den ASP.NET-Prozess vom IIS) ranhängt. Mehr ist nicht nötig.

Gruß
Juy Juka

23.05.2009 - 21:26 Uhr

Hallo ErfinderDesRades,

Die BindingSource ist auch für einzelne Objekt zu gebrauchen, man muss die einzelnene Objekte jedoch in eine Auflistung packen, damit die BindingSource das kapiert.

Aber zu erst zu dem Code mit typeof diese Zeile braucht nur der VisualDesigner vom Visual Studio. Des halb steht Sie auch normal nur in der *.Designer.cs .

Man muss im Code nur die konkrete instanz der BindingSource zu weisen, ca. wie folgt:

bindingSource.DataSource = new MyController[]{myController};

Gruß
Juy Juka

[EDIT]PS: Ach ja, das was herbivore gesagt hat stimmt. Fast alle Controls und Componenten (auch die BindingSource) funktionieren nur im GUI-Thread und das DataBinding sollte definitv auch nur im GUI-Thread stadtfinden, da es sonst verdamt kompliziert wird.[/EDIT]