Laden...

Forenbeiträge von xbredoillex Ingesamt 46 Beiträge

26.02.2010 - 19:02 Uhr

Hallo dennisspohr,

eine richtige Lösung für das Problem habe ich nicht gefunden bzw. ab einem gewissen Punkt nicht weiter nachgeforscht.
Mein letzten gespeicherten Links zu dem Thema waren diese hier:

http://blog.norberteder.com/comments.php?y=07&m=11&entry=entry071119-164324
http://www.silverlightshow.net/items/Using-the-Canvas-control-in-Silverlight-2-Beta-1.aspx

Vielleicht hilft dir das ja weiter. Ich erinnere mich, dass ich das damals irgendwie umsetzen wollte.

Gruß
xbredoillex

13.02.2010 - 15:17 Uhr

Hallo,

falls du es noch nicht kennst bringt dich das hier vielleicht weiter:Building an Extensible Application with MEF, WPF, and MVVM

Das funktioniert ausgezeichnet und ist relativ schnell zu durchschauen. Die Bewertungen sprechen auch für sich. Man kann die Library sehr leicht anpassen (z.B. das Physics2D rausnehmen) und sich somit seine eigene kleine aber feine Library basteln. Auf der im Artikel erwähnten Projekseite sind weitere Infos und ein WIKI.

Gruß
xbredoillex

08.02.2010 - 22:04 Uhr

Danke für die Beiträge.

Es ist deutlich schneller und Erfahrungsreicher, wenn du mal mit etwas anfängst,
das einigermassen Sauber Strukturiert ist, und das dann mit der Zeit Refactorierst,
als jetzt noch weiter Monatelang zu Planen und den Kopf voll zu machen.

Da hast Du nicht ganz unrecht und ich werde mir das zu Herzen nehmen.

Über weitere Demoprojekte oder Tutorials zur Anwendung von SQLite mit ADO.NET, egal welcher Art, würde ich mich dennoch sehr freuen. 🙂

Gruß
xbredoillex

08.02.2010 - 12:40 Uhr

Hi,

ich weiß, meine Angaben sind sehr allgemein gehalten. Das liegt vor allem an den sich ständig ändernden Parameter die meine Vorstellungen und Ziele jedesmal umschmeissen.

MVP/MVC/MVVM sind dann der nächste Punkt.
Was willst du machen? WindowsForms/WPF?

Gut, dass du das ansprichst, das ist nämlich auch so ein Faktor der mich viel Zeit und Nerven gekostet hat ohne je zu einem richtigen Entschluss gekommen zu sein. Eigentlich wollte ich das in WPF mit MVVM machen. Dann habe ich erstmal feststellen müssen, dass z.B. der Kalender in WPF nur als "3rd-Party-Fremdcontrol" existiert oder Datagridview etc. nicht existieren oder ähnliche Controls über irgendwelche Toolkits eher schlecht als recht eingebunden werden müssen und verbugt sind. Viele Toolkits oder Demos laufen entweder gar nicht oder nur mit viel Aufwand mit VS2008 Express bzw. Sharpdevelop3 o. 4.
Um die Frage zu beantworten: Ich habe mich noch nicht festgelegt. Ich würde wegen der schönen Binding-Eigenschaften und der späteren schöneren Grafikmöglichkeiten WPF mit MVVM bevorzugen, aber für den Einstieg und das Verständnis wäre auch WinForm kein Problem. Was würdest du (rein objektiv) in diesem Fall nehmen?

Die gute Trennung der einzelnen Schichten ist zwar in allen diesen Projekten wichtig,
aber das wie hängt dann doch eher davon ab, was dabei herauskommen soll.

Das ist auch noch nicht 100%ig festgelegt. Nur die groben Eckdaten sind klar. Es soll eine Desktopanwendung für den privaten Einsatz werden. Gleichzeitig wollte ich die Anwendung für zukünftige Änderungen und Erweiterungen sauber aufbauen und z.B alles in Schichten trennen.
Weiter kann ich mich noch nicht festlegen, denn es gibt zu viele Unklarheiten und Stolpersteine.

Die späteren Abfragen der Datenbank sollen umfangreiche statistische Auswertungen erlauben. Da herrschen bei mir auch die Fragezeigen. Die Beschaffung der Daten findet im DAL statt, die Filterung wird jedoch von manchen in die BL gelegt und andere wiederum sehen das als eine reine Darstellung der Daten und legen dies in die GUI, was bei WPF/Winform völlig unterschiedlich zu handhaben wäre. Außerdem kommt es dann zu den Fragen, ob alles in SQL zu machen ist und wenn nicht, wie und an welcher Stelle sonst.

Genau diese Dinge sind es die mir den Einstieg sehr schwer machen. Ich habe einfach Angst, dass sobald ich mich auf etwas festgelegt habe, irgendeine der Entscheidungen die Sache an späterer Stelle extrem verkompliziert und ich vielleicht ganz von vorne anfangen muss.

Gruß
xbredoillex

07.02.2010 - 22:57 Uhr

verwendetes Datenbanksystem: SQLite

Hallo,

ich möchte mich mit Datenbankanwendungen befassen. Wie in meinem letzten Beitrag beschrieben habe ich mir dazu ein Projekt überlegt, welches langsam und schrittweise ausgebaut werden soll. Zuerst soll ein einfaches Haushaltsbuch entstehen. Mit dem Datenbankdesign und den NF habe ich mich ausgiebig beschäftigt und komme gut zurecht.

Da ich jedoch noch absolut nichts mit Datenbanken zu tun hatte, baue ich zur Zeit auf gefährlichem Halbwissen auf. Der fehlende Überblick lässt mich leider auch keinen weiteren Einstieg in die Sache finden.

Es scheint irgendwie für jeden Bereich des Themengebiets mehrere Ansätze zu geben. Manches ist kombinierbar, manches schließt sich gegenseitig aus, manches ist optional, manches unterstützt einander. Obwohl ich viele Quellen gelesen und viel dazu gelernt habe, ist mir immer noch unklar, über welches Projekt-Design ich den Zugriff auf die Datenbank gestalten soll. Welche Technik ist angemessen und state of the art? Stichworte wären z.B. Erweiterbarkeit, Speicherbedarf, Dataset, ADO.NET, OR-Mapper, Entity Framework. Mehr lesen führt im Moment wegen der Vielfalt und Komplexität zu mehr Verwirrung.

Die ganze Theorie ist ohne praktische Anwendungen kaum erfassbar. Ich habe einige kleine SQLite-Beispielprojekte im Internet gefunden, diese sind jedoch für reale Anwendungen nicht zu gebrauchen, da sie sehr spärlich ausfallen (z.B. eine einzige Program.cs-Datei für alles, Konsolenausgabe). Beim Versuch in die Thematik einzusteigen bringt das einen nicht sonderlich weiter.

Ich komme einfach nicht dahinter, wie ich z.B. ADO.NET, SQLite und GUI, BL, BO und DAL zu einem sinnvollen Ganzen kombinieren kann. Deshalb suche ich verzweifelt ein Beispielprojekt in dem über das 3-Schichten-Modell auf eine Datenbank zugegriffen wird und die Daten über Databinding in beide Richtungen mit der GUI verstrickt werden.

Auch wenn ich überfordert erscheine, hat jemand Tipps oder kennt jemand ein Beispielprojekt oder ein Tutorial das über eine Konsolenanwendung hinaus geht und mir weiterhelfen könnte?

Gruß
xbredoillex

31.01.2010 - 21:26 Uhr

Alles klar, vielen Dank!

31.01.2010 - 20:11 Uhr

Hi,

nene, keine Sorge, ich meine schon Bilder u.ä.

Mir ist nur noch nicht klar, wie z.B. ein JPG in die Datenbank kommt.
Bisher habe ich immer nur Beispiele mit Datensätzen aus Datentypen wie int oder string gesehen. Deshalb dachte ich anfangs, solche DB könnten nur einige wenige Datentypen aufnehmen bzw. nicht mit JPG umgehen und habe naiverweise angenommen, die DB kann nur einen Verweis auf das Bild, aber nicht das Bild selbst aufnehmen.

Gruß
xbredoillex

31.01.2010 - 19:44 Uhr

Hallo,

Das ist natürlich mit einer DB möglich, allerdings sind das recht unterschiedliche Bereiche. Geht schon fast ein bisschen in den EAI (Enterprise Application Integration) Bereich 👅

Mein Vorhaben hört sich schon etwas "größer" an, aber ich will das ja nicht alles auf einmal programmieren. ich werde mich zunächst mit dem Haushaltsbuch beschäftigen. Ich will mir nur vorab sicher sein, das Gröbste in die Planungen einbezogen zu haben und eine gewisse Flexibilität für die Zukunft zu bewahren.

Es gibt nichts was eine ODB kann das mit einer RDB nicht möglich wäre.

Das klingt gut. ODB sind offenbar nicht so stark verbreitet und scheinen eher Nischenprodukte zu sein.

Das Problem bei der Frage nach der "richtigen" Datenbank ist einfach dass das zum großen Teil Geschmackssache ist.

Das ist gut zu wissen und für einen Einsteiger nicht so leicht von einem objektiven Vorschlag zu unterscheiden. Jetzt weiß ich, warum sich in einigen Beiträgen die Aussagen anhören als bestünde ein Werbeabkommen. 🙂

Auch hat SQLite keine 4GB Begrenzung, die dann ins Spiel kommen kann,
wenn man viele Binäre Daten in die DB speichern will.

Daraus entnehme ich, dass man die nicht unterstützen Datentypen auch irgendwie unterbringen kann.

Und die Windows Version unterstützt eben auch Verschlüsselung.

Das ist einer der Gründe weshalb ich Firebird Embedded nicht verwende. Dort wäre ein Verschlüsseln meiner Ansicht nach umständlich.

So wie es aussieht werde ich jetzt SQLite verwenden. Und NHibernate scheint es auch Wert zu sein, sich damit zu beschäftigen.
Jetzt brauche ich nur noch ein gutes Tutorial, vor allem eines worin erklärt wird, wie man die erwähnten binären Dateien "verwurstet". Vielleicht hat ja jemand noch ein paar gute Tipps oder Links zu solchen.

Vielen Dank nochmal.

Gruß
xbredoillex

31.01.2010 - 13:51 Uhr

Offenbar kann man sich wegen der großen Unterschiede nicht einfach mal eben mit Datenbanken beschäftigen. Man kann so wie es aussieht immer nur mit einem Datenbanksystem Erfahrungen sammeln, die für andere DB-Systeme nicht übertragbar sind. Es gibt nur einen sehr kleinen gemeinsamen Nenner. Oder irre ich mich?

Ich habe nun genauere Vorstellungen was mein Programm beinhalten soll.
Ich möchte sowohl mein Haushaltsbuch als auch mein Tagebuch auf dem PC weiterführen. Und das soll mit einem einzigen Programm geschehen. Darum war auch eine Verschlüsselung angedacht.
Vom Prinzip her soll im Hauptfenster ähnlich wie in einem Terminplaner ein Kalender angezeigt werden. Beim Klicken auf einen Tag, sollen dann die entsprechenden Daten angezeigt werden. Man kann zwischen Tagebuch und Haushaltbuch-Modus umschalten. Über eine Suchmaske können Informationen gesucht werden.

Mir schwebt z.B. folgendes vor:

  • suche alle Tage, in deren Tagebucheinträgen das Wort "Fußball" vorkommt oder die Worte "Date, Tanja" enthalten sind
  • suche alle Tage an denen ich mein Auto betankt habe
  • summiere mir alle Kosten die mir mein Auto für den Zeitraum x verursacht hat (Auto ist im Haushaltsbuch ein Posten mit fixen und nicht fixen Kosten)
  • summiere mir alle Kosten für Kleidung im Jahr 2009

Geht das überhaupt mit einer relationalen Datenbank umzusetzen?
Ich glaube nicht mehr, dass SQLite das Richtige ist. Wie verhält sich das eigentlich mit langen Texten in SQLite?
Also kann ich da nen seitenfüllenden Tagebucheintrag einer RichTextBox einlesen und vernünftig verwalten?

Wäre eine Objektdatenbank angebracht? Diese hätte dann den Vorteil, dass man auch Fotos einer Geburtstagsparty in den Tagebucheintrag einbetten kann, oder Kopien von Rechnungen etc.
[Edit/Nachtrag] Kann man das mit NHibernate und SQLite auch umsetzen?

Was würdet ihr erfahrungsgemäß für ein Datenbanksystem für diesen Anwendungszweck einsetzen?
Gibt es Bedenken oder Tips?

Gruß
xbredoillex

PS: Ich hoffe ich konnte meine Problematik etwas besser darstellen als in meinem Startbeitrag 😃

31.01.2010 - 13:06 Uhr

Hallo,

@ Florian Reischl
Sorry, ich habe hoffentlich nicht den Eindruck eine "faulen Nichtsuchers" erweckt, der eine Lösung präsentiert haben will. Ich hätte meine Frage etwas anders formulieren sollen und genauer beschreiben sollen, welche Datenbanken ich schon eingegrenzt habe und wobei ich mir bei diesen unsicher bin.

Das mit der Suche ist so ne Sache bei Datenbankthemen. Wenn man nicht genau weiß nach was man im Web suchen soll, dann dreht man sich im Kreis. Allein der Begriff "embedded" bringt einen bespielsweise schon viel weiter, den muss man aber erstmal kennen um danach zu suchen.
Wenn man am Anfang steht kommt, kann man nicht wirklich voraussehen ob man eine relationale, objektorientierte oder objektrelationale Datenbank benötigt, oder evtl. doch ne eigene XML-basierte Lösung anstrebt oder LINQ2XML verwendet etc.
Viele Beiträge im Forum sind z.B. veraltet (2005) und berücksichtigen die Möglichkeiten von .Net 3.5 oder 4 nicht, oder es gab es zu diesem Zeitpunkt noch keine C#-dlls für "diese oder jene" Datenbank.
Man findet vor allem immer wieder Beiträge in denen alle gängigen Datenbanken aufgezählt werden, aber entweder sind die Antworten zu speziell und mit unbekannten Akronymen gespickt (das Nachlesen dieser ist nicht immer fruchtbar oder verständnisfördernd, eher verwirrend und unverhältnismäßig zeitraubend), oder man findet Beiträge in denen darauf hingewiesen wird, dass die Frage schon oft gestellt wurde (ist nicht böse gemeint) 😃.

@ FZelle
SQLite war schon in meiner engeren Wahl, ich glaube das werde ich nehmen.

Gruß
xBredoillex

30.01.2010 - 19:31 Uhr

verwendetes Datenbanksystem: keins

Hallo,

ich würde mich gerne in das Thema Datenbanken einarbeiten. Dazu will ich mir eine Art Haushalts-/Tagebuch programmieren, in dem z.B. Ausgaben und andere Dinge gespeichert werden und im Nachhinein gefiltert wieder abrufbar sein sollen. z.B. wie viel habe ich für McDo.... oder für Döner ausgegeben, wieviel habe ich im Januar in Bier investiert? =)
[Edit/Anmerkung: Im Beitrag von 31.01, 13:51 Uhr habe ich meine Vorstellungen noch einmal präziser dargestellt 🙂]

Kriterien für die Auswahl einer Datenbank sind für mich:

  • am besten sollte man nichts Zusätzliches (server o.ä.) installieren müssen
  • die Daten sollten in einer einzelnen Datei lagern (ähnlich z.B. ein Excelfile), um sie bei Bedarf problemlos finden und sichern zu können
  • die Datenbank sollte mit c# unkompliziert zu handhaben sein
  • die Datenbank sollte einigermaßen System- oder Sprachunabhängig sein
  • evtl. verschlüsselbar
  • und das Wichtigste: sie muss kostenlos sein

Nun habe ich versucht mich für eine bestimmte Datenbank zu entscheiden, komme aber zu keinem Schluss. Es gibt irgendwie zu viele Unterschiede und Vor- und Nachteile, das macht eine Entscheidung irgendwie echt schwer wenn man noch nie etwas mit Datenbanken zu tun hatte.

Meine Frage an euch:
Welche Datenbankart, welches System, welche Technik würde sich für meinen Anwendungszweck anbieten?

Vielen Dank im voraus.

Gruß
xbredoillex

20.01.2010 - 10:43 Uhr

Hallo danielpalme,

vielen Dank für deine Antwort.
Nicht nur, dass du mir weitergeholfen hast, beim Verstehen deines Lösungsansatzes habe ich auch noch sehr viel dazu gelernt.

Was hier auf den ersten Blick so einfach aussieht hat es meiner Meinung nach ganz schön in sich. Da kommt man (als durchschnitts-C#-Hobbyprogrammierer) nicht eben mal schnell drauf.

Diese sehr elegante Methode war für mich z.B einer der Schlüssel die mir gefehlt haben.


public bool ContainsElement(A element)
{
	return this.UnterElemente.Contains(element) || this.UnterElemente.Count(e => e.ContainsElement(element)) > 0
}

Wenn ich das richtig verstanden habe funktioniert sie so:
Bedingtes OR, wenn der linksseitige Ausdruck true ist, wird, da bei OR ein true insgesamt true ergibt, der rechtsseitige Ausdruck nicht ausgewertet und return ist true.
Ist die linke Seite false, wird der rechtsseitige Ausdruck ausgewertet. Dort wird bei allen UnterElementen deren Unterelementeanzahl > 0 ist ein rekursiver Aufruf gestartet.

Nochmals vielen Dank für deine Mühen.

Liebe Grüße
xbredoillex

19.01.2010 - 14:45 Uhr

verwendetes Datenbanksystem: keines

Hi,

auf Basis der ganz unten gezeigten Klasse A wird eine Baumstruktur erzeugt.

Über Linq soll nun bei zwei gegebenen Elementen E1 und E2 folgender Vergleich durchgeführt werden:
Falls in E2 ein Unterelement X vorkommt, dass in E1 nicht enthalten ist, soll X (und seine Unterelemente) in E1 an äquivalenter Stelle mit der Funktion "AddElement(parentInE1, X)" eingefügt werden.

Irgendwie komme ich auf keinen sinnvollen Ansatz das zu bewerkstelligen. Ich finde immer nur Beispiele und Erklärungen die sich mit einer Schachtelebene befassen, kann diese aber nicht auf mein Problem ummünzen.

Geht das was ich vorhabe überhaupt über Linq?
Muss da ein rekursiver Aufruf der Linq-Abfrage erfolgen oder geht das innerhalb einer Abfrage in einem Rutsch?

Hat jemand eine Idee wie ich das machen kann?

Gruß
xbredoillex

Hier ist noch das Schema der schachtelbaren Klasse A:


public class A
{
    public A()
    {
        UnterElemente = new List<A>();
    }
    public string Name { get; set; }
    public A Parent { get; set }
    public List<A> UnterElemente { get; set; }
    ...
}

19.12.2009 - 18:47 Uhr

Hallo herbifore,

das macht doch keinen Unterschied.

Tja, Hüstel, was soll ich sagen?

Nochmals nachgelesen, Gehirn eingeschaltet und nach minimalen Anpassungen deiner Lösung aus dem Beitrag TreeView abhängig vom Verzeichnislevel füllen hat es auch schon funktioniert. 😃

Falls es jemanden interessiert, hier die Lösung:

Die Klasse BaumElement (leicht abgeändert)


	public class BaumElement
	{
		public BaumElement()
		{
		}
		
		public BaumElement(string name)
		{
			Name = name;
		}
		
		private List<BaumElement> _children = new List<BaumElement>{}; 
		
		public string Name {get; set;}
		
		public BaumElement Parent {get; set;}
		
		public List<BaumElement> Children
		{
			get {return _children;}
			set {_children = value;}
		}
		
		public BaumElement FuegeNeuesUnterelementEin(BaumElement neuesElement)
		{
			neuesElement.Parent = this;
			Children.Add(neuesElement);
			return neuesElement;
		}
	}


Die Funktion zum Füllen des Baumes:


	public BaumElement ErzeugeBaum(List<string> pfadliste)
	{
		Dictionary <String, BaumElement> dictElement = new Dictionary <String, BaumElement> ();
		BaumElement gefuelltesBaumElement = new BaumElement("Wurzel");
		BaumElement wurzelElement = null;
		foreach (string pfad in pfadliste)
		{
			string[] teilPfadArray = pfad.Split('/');
			string teilPfad = String.Empty;
			
			for(int i=0; i<teilPfadArray.Length; i++) {
				
				string teilStr = teilPfadArray[i].Trim();
				
				if (teilStr.Equals(String.Empty))
					break;
				
				if (teilPfad.Equals(String.Empty))
					teilPfad = teilStr;
				else 
					teilPfad = String.Concat(teilPfad, "/", teilStr);
				
				if (dictElement.ContainsKey(teilPfad)) {
					wurzelElement = dictElement[teilPfad];
					continue;
				}
				
				dictElement[teilPfad] = new BaumElement(teilStr);
				
				if (i==0)
					gefuelltesBaumElement.FuegeNeuesUnterelementEin(dictElement[teilPfad]);
				
				if (wurzelElement == null)
					wurzelElement = dictElement[teilPfad];
				else 
					wurzelElement.FuegeNeuesUnterelementEin(dictElement[teilPfad]);
				
				wurzelElement = dictElement[teilPfad];
			}
		}
		return gefuelltesBaumElement;
	}

Danke und Gruß,
xbredoillex

19.12.2009 - 14:18 Uhr

Hallo,

es will mir nicht gelingen, aus einer Liste mit Pfadangaben eine Baumstruktur zu erzeugen.

Das Thema wurde hier und an anderer Stelle schon oft besprochen, jedoch immer im Bezug auf TreeNodes, während ich das Ganze über verschachtelte Klassen lösen muss.

Mein Ansatz sieht bisher so aus:

Die Pfade befinden sich in einer String-Liste, z.B.


public List<string> pfadliste = new List<string> {	"Tiere/Weichtiere/Kopffuessler/Krake",
													"Tiere/Weichtiere/Schnecken",
													"Tiere/Wirbeltiere/Amphibien/Frosch",
													"Tiere/Wirbeltiere/Amphibien/Schwanzlurche",
													"Tiere/Wirbeltiere/Fische",
													"Tiere/Wirbeltiere/Reptilien/Schlange",
													"Tiere/Wirbeltiere/Saugetiere/Nager/Hamster/Zwerghamster",
													"Tiere/Wirbeltiere/Saugetiere/Primaten/Menschenaffen/Gorilla",
													"Tiere/Wirbeltiere/Saugetiere/Primaten/Menschenaffen/Mensch",
													"Tiere/Wirbeltiere/Voegel" };

Jedes Element aus einem Teilpfad soll von einem Objekt der Klasse BaumElement dargestellt werden:


	public class BaumElement
	{
		public BaumElement()
		{
		}
		
		public BaumElement(string name, BaumElement parent)
		{
			Name = name;
			Parent = parent;
		}
		
		private List<BaumElement> _children = new List<BaumElement>{}; 
		
		public string Name {get; set;}
		
		public BaumElement Parent {get; set;}
		
		public List<BaumElement> Children
		{
			get {return _children;}
			set {_children = value;}
		}
		
		public BaumElement FuegeNeuesUnterelementEin(string name, BaumElement parent)
		{
			BaumElement neuesElement = new BaumElement(name, parent);
			Children.Add(neuesElement);
			return neuesElement;
		}
	}

Und zuletzt noch die Funktion ErzeugeBaum, die das befüllte Wurzel-BaumElement-Objekt zurückgeben soll:


public BaumElement ErzeugeBaum(List<string> pfadliste)
{
	BaumElement rootElement = new BaumElement();
	foreach(string pfad in pfadliste)
	{
		string[] teilPfadArray = pfad.Split('/');
		for (int i=0; i<teilPfadArray.Length; i++) {
			string teilpfad = teilPfadArray[i];
			//
			//Bis hierher funktioniert es, aber dann verließen sie ihn...
			//TODO: Erzeuge mit BaumElementen (über Name, Parent, Children) 
			//die verschachtelte Baumstruktur (Funktion? Rekursiv?).
			//
		}
	}
	return rootElement;
}

Die Funktion erzeugt für jeden Pfad der Liste ein Teilpfadarray, in dem die einzelnen Namen der zu erzeugenden BaumElemente abgelegt sind. Die Reihenfolge der Namen enspricht der Beziehung Wurzel>KindvonWurzel>Kindvon(KindvonWurzel)>etc. wobei ich eben nach vielen Versuchen nicht in der Lage bin, das mit einer Funktion zu beschreiben um die Elemente entsprechend zu erzeugen.

Hat jemand einen Tipp für mich?

Vielen Dank im voraus!
Gruß
xbredoillex

24.11.2009 - 12:53 Uhr

Hi,

wenn ich das Images Verzeichnis in bin einfüge, kopiert es mir dann beim Einfügen in den Projektesplorer das Verzeichis zusätzlich automatisch in das Projektverzeichnis und setzt das als Referenz. Aber die Bilder werden immer noch nicht gefunden.

[EDIT]

Quaneu:

Probier mal bei den Properties des Bildes die Build Action auf Resource zu setzen.

Das war das ganze Problem, jetzt gehts.

Muss man das immer machen? Ich habe das noch nirgends gelesen.

Nochmals Danke an alle.

24.11.2009 - 10:34 Uhr

Hallo,

beim Versuch ein Icon aus einem Projektverzeichnis zu laden bekomme ich die Fehlermeldung:


System.Windows.Markup.XamlParseException: Die Zeichenfolge "/Images/TestIconDark.png" im Attribut "Source" kann nicht in ein Objekt vom Typ "System.Windows.Media.ImageSource" konvertiert werden. Die Ressource "images/testicondark.png" kann nicht gefunden werden.  Fehler in Objekt "System.Windows.DataTemplate" in Markupdatei "WPFTest;component/TestResources.xaml", Zeile 13, Position 14. ---> System.IO.IOException: Die Ressource "images/testicondark.png" kann nicht gefunden werden.

Das Image ist in einer ResourceDictionary wie folgt eingebettet:


<ResourceDictionary 
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ...>
        <DataTemplate ... >
             <StackPanel ... >
                   <Image x:Name="DarkIcon" Source="/Images/TestIconDark.png" />
        [...]


Das Verzeichnis "Images" befindet sich im Projektordner genau dort, wo die anderen Dateien wie z.B. "WPFTest.csproj" oder "Window1.xaml" liegen. Das png ist definitiv im Verzeichnis drin und die Namen stimmen auch alle. Das Verzeichnis habe in das Projekt mit "Hinzufügen -> Verzeichnis" eingebunden.

Versucht habe ich, unter anderem, die png-Datei direkt ins Debug/Bin-Verzeichnis zu legen. Auch mit den relativen Pfadangaben habe ich gespielt (../, ohne /, mit/ vor Images etc). Leider kommt immer die gleiche Fehlermeldung, nur dass sich dort die Meldung entsprechend meiner Eingabe bei Source ändert.

Das seltsame ist, ich habe als Vorlage zu meinem Code den Code eines Demoprojekts genommen. Dort funktioniert es mit gleicher Verzeichnisstruktur und den gleichen Angaben im Code ohne Probleme.

Wo könnte das Problem liegen bzw. wie könnte ich weiter vorgehen?

Gruß
xbredoillex

20.11.2009 - 14:19 Uhr

Hallo,

erstmal Danke für die Antworten. Gut das ich nicht der Einzige bin der dieses Problem hat. Das macht einem etwas Mut nicht an Banalitäten zu scheitern.

Ich hatte mir das Framework von Sacha Barber schon angeschaut, finde es aber, wie Lector schon gesagt hat, etwas überdimensioniert. Als Einsteiger ist es sehr schwer daraus etwas zu lernen, wenn man nicht schon einen gewissen Kenntnisstand hat. So wie ich das verstehe, ist seine Lösung über einen "Service" aufgebaut und für sein Framework zugeschnitten.

Leider ist mir bei MVVM-Frameworks und anderen eine große Gemeinsamkeit aufgefallen - nämlich, dass sie nicht viel gemeinsam haben. Sie sind nicht kompatibel zueinander, verfolgen verschiedene Philosophien und Lösungsansätze für ein und die selbe Sache, sind z.T. sehr komplex und fördern nicht gerade das Erlernen von Basiswissen. Zudem schnürt man sich beim Festlegen auf ein Framework in der Programmierfreiheit extrem ein.

So genial ein Framework sein mag, immerwieder stößt man erst nach einer ganzen Weile auf einen gravierenden Nachteil der nicht vorhersehbar war und der in anderen Frameworks nicht besteht. Was dann? Sich in ein neues Framework einarbeiten und alles umschreiben oder das Framework selbst umschreiben, sofern man es darf/kann? Die Katze beisst sich in den Schwanz.

Nun gut, von der Frameworkproblematik zurück zum Thema.
Ich suche nach einem simplen und frameworkunabhängigen Lösungsschema. Es muss weder elegant noch leichtfüßig sein, sondern lediglich verständlich machen, wie man vorgeht und worauf es ankommt um im MVVM-Pattern zu bleiben.
[Edit: Eine Helperclass ist noch kein Framework 😉]

@Mr Evil:
Könntest du (frameworkunabhängig) und in Bezug zu meinem Eröffnungspost näher erklären wie du das umgesetzt hast? Ich wäre schon für Stichpunkte dankbar.

Gruß
xbredoillex

19.11.2009 - 22:44 Uhr

Hallo,

ich versuche mich gerade an WPF mit MVVM. Da ich nur einen groben Überblick habe, sitze ich gerade bei etwas vermutlich ganz banalen auf dem Schlauch.

Meine Anwendung hat ein Hauptfenster mit einem Button1 der ein modales Fenster öffnen soll.
Nun habe ich ein Model, ein ViewModel um das Model für die View "geschmeidig" zu machen und zuletzt eine View, welche aus einem Window besteht, das Textboxen und Buttons des Dialogs enthält.

Frage: Wie starte ich nun über Button1_click die ganze Geschichte so, dass es MVVM-konform ist und ich gleichzeitig View und ViewModel binden kann?

Soll aus Button1_click heraus a) je eine Instanz von View und Viewmodel erzeugt werden? Problem: Da das View das Viewmodel nicht kennt, wie komme ich im xaml ohne Code-Behind an dessen Referenz um zu binden?

b) eine Instanz der View erzeugt werden und aus der View heraus eine Instanz des ViewModels? Problem: Da ViewModel nichts von View weiß, wie bekommt ViewModel ein Schließen von View mit?

c) keine der beiden vorangegangenen Optionen verwendet werden, sondern was ganz anderes und völlig abgefahrenes?

Die Daten sollen dann beim Schließen des modalen Dialogfensters an ein drittes ViewModel weitergeleitet werden, wobei ich da auch wegen dem MVVM nicht ganz durchsteige, das sei aber nur am Rande erwähnt und Thema für einen anderen Thread.

Gruß xbredoillex

20.10.2009 - 17:33 Uhr

Danke für die Infos, ich glaube ich habe es jetzt gerafft 😃

Ab "wann" ist eine Validierung im Setter einer nicht all zu häufig gesetzten Property zu viel und sollte vermieden werden? Kann man das irgendwo festmachen (z.B. eine Faustregel)?
Ist eine komplexe Regex-Abfrage noch tolerierbar oder ist unter "zu viel" eher sowas wie vergleiche mit Datenbankeinträgen oder ähnlichem zu verstehen?

Gruß
xbredoillex

20.10.2009 - 11:43 Uhr

Hi,

ich experimentiere gerade mit IDataErrorInfo.

In der unten angehängte Klasse Person habe ich IDataErrorInfo (hoffentlich richtig) implementiert.

Leider komme ich an dieser Stelle nicht mehr weiter. Irgendwie erschließt sich mir nicht, wie man mit diesem Interface arbeitet und ich habe bisher kein Beispiel gefunden, das mir wirklich weiter hilft.

Angenommen ich hätte ein Objekt der Klasse Person und auf einem Form eine Textbox und ein Label.
Wie muss ich vorgehen, wenn über die Textbox ein Vorname für person.Vorname eingegeben wird und die Validierungsinformationen, falls vorhanden, im Label erscheinen sollen?
Wie komme ich an die IDataErrorInfo?

Gruß

xbredoillex



using System.ComponentModel;

namespace WindowsFormsApplication1
{
    public class Person : IDataErrorInfo
    {
        public string Vorname { get; set; }
        public string Nachname { get; set; }

        public Person()
        {
        }

        public string Error
        {
            get { return null; }
        }

        public string this[string propertyName]
        {
            get
            {
                if (propertyName == "Vorname")
                {
                    if (string.IsNullOrEmpty(Vorname))
                        return "Vorname fehlt";
                }
                
                if (propertyName == "Nachname")
                {
                    if (string.IsNullOrEmpty(Nachname))
                        return "Nachname fehlt";
                }

                return null;
            }
        }
    }
}


14.10.2009 - 16:40 Uhr

Hi,

danke für den Tipp, mit MouseEnter/Leave geht es jetzt halbwegs.

Sieht halt nicht so toll aus, wenn das aktuelle Objekt beim Loslassen wieder hinter einem anderen verschwindet. Es wäre schöner wenn die Ebenen in der Reihenfolge des Anklickens sortiert sind und nicht in der Reihenfolge in der sie erschaffen wurden.

Es scheint wirklich so, als müsste man den ZIndex aller Objekte selbst verwalten, wenn man das anständig umsetzen will.

Dazu müsste man aber auch den ZIndex des verdeckenden, nicht angeklickten Objekts ermitteln um die Werte der Indizes evtl. zu vertauschen.

Nur wie? Hat jemand eine Idee?

Gruß
xbredoillex

Hier der Code mit MouseEnter/Leave:


public class MoveThumb : Thumb
	{
        private int tempindex = 0;
        
        public MoveThumb()
	    {
            MouseEnter += new MouseEventHandler(MoveThumb_MouseEnter);
            MouseLeave += new MouseEventHandler(MoveThumb_MouseLeave);
	        DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
	    }

        private void MoveThumb_MouseEnter(object sender, MouseEventArgs e)
        {
            ContentControl item = this.DataContext as ContentControl;
            if (item != null)
            {
                tempindex = Canvas.GetZIndex((UIElement)this.DataContext);
                Canvas.SetZIndex((UIElement)this.DataContext, 99);
            }
        }

        private void MoveThumb_MouseLeave(object sender, MouseEventArgs e)
        {
            ContentControl item = this.DataContext as ContentControl;
            if (item != null)
            {
                Canvas.SetZIndex((UIElement)this.DataContext, tempindex);
            }
        }

	    private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
	    {
            Control item = this.DataContext as Control;
	        if (item != null)
	        {	
	            double left = Canvas.GetLeft(item);
	            double top = Canvas.GetTop(item);
				
	            Canvas.SetLeft(item, left + e.HorizontalChange);
	            Canvas.SetTop(item, top + e.VerticalChange);
	        }
	    }
	}
}

14.10.2009 - 13:43 Uhr

Hi,

ich habe jetzt mit setZIndex() herumprobiert. Damit bringe ich das erste angeklickte Element in den Vordergrund. Leider geht das nur ein einziges mal beim allerersten angeklickten Objekt, dann verändert sich beim erneuten Bewegen eines Objektes die ZEbene nicht mehr.

Vermutlich, weil man beim setzen eines ZIndex immer die Indizes aller Objekte relativ dazu anpassen muss, sonst haben alle angeklickten irgendwann den gleichen ("obersten") Index. Kann das so stimmen?
Bei BringToFront()/SendToBack() ging das relative Setzen der Indizes automatisch.

Beim Versuch in MoveThumb_DragDelta() den ZIndex zu setzen kann man zwar den ZIndex des geklickten Objektes setzen, aber nicht den Index aller anderen anpassen. Innerhalb dieser Funktion bekommt man keinen Zugriff auf die anderen Elemente bzw. auf deren setZIndex-Funktion.

Das komplizierte Zugreifen auf die einzelnen verschachtelten Objekte macht es mir irgendwie unmöglich das Problem zu lösen, denn jede Schachtelebene hat völlig unterschiedliche Properties. Mal gibt es Parent/Child, mal nicht etc.
Ich habe es mit PreviewMouse-Events an verschiedenen Stellen versucht, da verheddere ich mich aber immer in den Schachtelebenen bzw. komme nicht weiter, weil ich die benötigten Objekte nicht erreichen kann.

Gibt es eine elegante Lösung, das mit Maus gegriffene Element immer in den Vordergrund zu bringen?

Gruß
xbredoillex

12.10.2009 - 21:53 Uhr

Hallo,

in dem im Anhang folgenden Codestück werden in einem Canvas zwei Figuren in jeweils einem ContentControl erzeugt, deren Größe und Position sich zur Laufzeit über Thumbs verändern lassen. Wenn man die Figuren übereinander schiebt ist immer die zuerst im Code erzeugte Figur im Vordergrund und überdeckt die andere.

Nun soll aber immer die gerade mit der Maus gepackte Figur im Vordergrund sein und beim Loslassen auch so verbleiben. BringToFront() gibt es ja nicht 😃 und irgendwie sitze ich mal wieder auf dem Schlauch.

Hat jemand einen Tip für mich?

Danke im voraus,
xbredoillex

ANHANG:

Die Code entstammt aus dem Projektordner "MoveResize" im Source-Download des Artikels http://www.codeproject.com/KB/WPF/WPFDiagramDesigner_Part1.aspx und kann dort direkt als Projekt gestartet werden.


<Window x:Class="DiagramDesigner.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:s="clr-namespace:DiagramDesigner"
        WindowStartupLocation="CenterScreen"
        Title="Move and resize"
        Height="550" Width="750">
  <Window.Resources>

    <!-- MoveThumb Template -->
    <ControlTemplate x:Key="MoveThumbTemplate" TargetType="{x:Type s:MoveThumb}">
      <Rectangle Fill="Transparent"/>
    </ControlTemplate>

    <!-- ResizeDecorator Template -->
    <ControlTemplate x:Key="ResizeDecoratorTemplate" TargetType="{x:Type Control}">
      <Grid>
        <s:ResizeThumb Height="3" Cursor="SizeNS" Margin="0 -4 0 0"
                       VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
        <s:ResizeThumb Width="3" Cursor="SizeWE" Margin="-4 0 0 0"
                       VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
        <s:ResizeThumb Width="3" Cursor="SizeWE" Margin="0 0 -4 0"
                       VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
        <s:ResizeThumb Height="3" Cursor="SizeNS" Margin="0 0 0 -4"
                       VerticalAlignment="Bottom" HorizontalAlignment="Stretch"/>
        <s:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="-6 -6 0 0"
                       VerticalAlignment="Top" HorizontalAlignment="Left"/>
        <s:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="0 -6 -6 0"
                       VerticalAlignment="Top" HorizontalAlignment="Right"/>
        <s:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="-6 0 0 -6"
                       VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
        <s:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="0 0 -6 -6"
                       VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
      </Grid>
    </ControlTemplate>


    <!-- Designer Item Template-->
    <ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
      <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
        <s:MoveThumb Template="{StaticResource MoveThumbTemplate}" Cursor="SizeAll"/>
        <Control Template="{StaticResource ResizeDecoratorTemplate}"/>
        <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
      </Grid>
    </ControlTemplate>

  </Window.Resources>

  <Canvas>
    <ContentControl Width="130"
                    MinWidth="50"
                    Height="130"
                    MinHeight="50"
                    Canvas.Top="150"
                    Canvas.Left="470"
                    Template="{StaticResource DesignerItemTemplate}">
      <Ellipse Fill="Red"
               IsHitTestVisible="False"/>
    </ContentControl>
    <ContentControl Width="130"
                    MinWidth="50"
                    Height="130"
                    MinHeight="50"
                    Canvas.Top="150"
                    Canvas.Left="150"
                    Template="{StaticResource DesignerItemTemplate}">
      <Path Fill="Blue"
            Data="M 0,5 5,0 10,5 5,10 Z"
            Stretch="Fill"
            IsHitTestVisible="False"/>
    </ContentControl>
  </Canvas>
</Window>


using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace DiagramDesigner
{
    public class MoveThumb : Thumb
    {
        public MoveThumb()
        {
            DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
        }

        private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Control designerItem = this.DataContext as Control;

            if (designerItem != null)
            {
                double left = Canvas.GetLeft(designerItem);
                double top = Canvas.GetTop(designerItem);
                Canvas.SetZIndex(designerItem, 0);
                Canvas.SetLeft(designerItem, left + e.HorizontalChange);
                Canvas.SetTop(designerItem, top + e.VerticalChange);
            }
        }
    }
}



using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace DiagramDesigner
{
    public class ResizeThumb : Thumb
    {
        public ResizeThumb()
        {
            DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta);
        }

        private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Control designerItem = this.DataContext as Control;

            if (designerItem != null)
            {
                double deltaVertical, deltaHorizontal;
                Canvas.SetZIndex(designerItem, 0);

                switch (VerticalAlignment)
                {
                    case VerticalAlignment.Bottom:
                        deltaVertical = Math.Min(-e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
                        designerItem.Height -= deltaVertical;
                        break;
                    case VerticalAlignment.Top:
                        deltaVertical = Math.Min(e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
                        Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + deltaVertical);
                        designerItem.Height -= deltaVertical;
                        break;
                    default:
                        break;
                }

                switch (HorizontalAlignment)
                {
                    case HorizontalAlignment.Left:
                        deltaHorizontal = Math.Min(e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
                        Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + deltaHorizontal);
                        designerItem.Width -= deltaHorizontal;
                        break;
                    case HorizontalAlignment.Right:
                        deltaHorizontal = Math.Min(-e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
                        designerItem.Width -= deltaHorizontal;
                        break;
                    default:
                        break;
                }
            }

            e.Handled = true;
        }
    }
}

29.09.2009 - 09:16 Uhr

Hallo,

danke, du hast mir jetzt meine Unsicherheit genommen, in drei Wochen wegen eines falschen Ansatzes von vorne beginnen zu müssen. 😃

Genau so werde ich es machen:
Erst ohne GUI programmieren, dann eine GUI erstellen bei der jedes Grafikobjekt eine Referenz auf das Datenobjekt hat. Die Grafikobjekte sind voraussichtlich Usercontrols Diese werden in einer Liste verwaltet.

Ich habe schon versucht ähnliche Projekte zu finden um eine Lösungsmethode für dieses "Problem" zu klau..., ähh, um mich inspirieren zu lassen. Aber leider habe ich trotz langer Suche nichts brauchbares finden können.
#Develop ist super, leider ist es schon sehr schwierig eine bestimmte Stelle im Quellcode zu finden. Den Code dann im Zusammenhang mit dem Gesamtprojekt zu verstehen und ihn auf mein "kleines" Problem herunter zu brechen fällt mir noch schwerer.

Zwecks Referenz auf das Datenobjekt, wie meinst du das hier genau?

Im Idealfall ist die Referenz noch auf ein Interface des Daten Objektes.

Gruß
xbredoillex

28.09.2009 - 18:36 Uhr

Das mit dem Drucken etc klingt einleuchtend. Wenn ich es richtig verstanden habe, sollen die Objekte hierarchisch auf gleicher Ebene existieren.

Angenommen, ich habe in meiner zukünftigen Anwendung einen Button "Klassenvorlage erzeugen". Dann entstehen bei jedem Klick zwei zusammengehörende Objekte: das Grafikobjekt der Gui-Klasse (evtl. Usercontrol) und das Datenhalterobjekt für die ins Grafikobjekt eingegebenen Klassendaten.

Da sich die Objekte nicht kennen (sollte wohl auch so sein um flexibel zu bleiben), weiß ich nun nicht, wie ich diese verwalten soll. Schließlich kommt ja mit jedem Klick ein weiteres Objektpaar hinzu und es kann auch sein das mal eines gelöscht werden muss oder editiert werden soll.

Meine Idee, die Objektpaare in einer Liste zu verwalten, zwingt mich irgendwie das Paar in einer weiteren Listenelement-Klasse zu Kapseln. Damit wäre aber wieder eine Verbindung von Gui und Daten geschaffen.

Irgendwie komme ich immer wieder an diese Stelle und dort jedoch mangels an Erfahrung nicht weiter 😃.

Ich erweitere mal die Topicfrage mit: ...und wie verwalte ich gewisse Anzahl an Gui-Daten-Objektpaaren, deren Objekte sich nicht kennen sollten?

Auf welche Art würdest du denn diese Objektpaare verwalten, so dass Änderungen am Gui-Objekt eine Objektpaares sich auf das zugehörige Datenobjekt auswirken u.u.?

28.09.2009 - 15:21 Uhr

Hi,

ich möchte eine Art grafischen Klassendesigner programmieren. Ähnlich wie bei Klassendiagrammen soll man die Klassen als bewegliche Rechtecke dargestellt mit Verbindungen und Informationen wie Methoden, Eigenschafte usw. ausstatten können. Später sollen vielleicht die Klassenrümpfe generiert werden.

Vorneweg, ich weiß, dass es schon fertige Programme gibt, aber ich wollte so etwas selbst programmieren um C# zu lernen.

Zur grafischen Darstellung gibt es hier super Tutorials und ich habe das gut im Griff.

Mein Hauptproblem liegt im Softwaredesign und bei der Planung. Hier herrscht die große Unsicherheit, weshalb ich euch um Rat bitte.

Konkreter: Wie baue ich so etwas auf ohne die Grundlagen der OO zu verletzen und ohne mir bei einer späteren Erweiterung ins Knie zu schießen? Wie trenne ich sinnvoll Daten, Gui und den Rest (Stichwort MVC-Pattern)?

Folgende Fragen stellen sich mir:

Das Grafikobjekt "Klassenrechteck", welches die Klasse darstellen soll, soll es auch die Informationen zur Klasse (Methoden-, Feldnamen usw.) Speichern? Dann wären jedoch Gui und Daten vermischt.

Oder sollte es umgekehrt gemacht werden, so dass das Datenobjekt ein Grafikobjekt von sich selbst erzeugt? Dann gibt es ja wieder keine Trennung von Gui und Daten, oder?

Wenn ich ein Datenobjekt für Klassendaten und eines für dessen Grafikdarstellung, verwende kann ich diese beiden dann sinnvoll und unkompliziert gleichzeitig verwalten (Änderungen synchronisieren, Erstellen, Löschen)?

Zuletzt habe ich mir überlegt, als Klassengrafik-Objekt ein Usercontrol zu erzeugen, weiß aber nicht ob das eine glückliche Wahl ist. Anbindung der Daten über Databinding?

Nun ja, ich hoffe auf zahlreiche Tipps und Tricks die mir Licht ins Dunkle bringen.

Gruß
xbredoillex

21.09.2009 - 18:47 Uhr

Hallo,

ich möchte in einem PropertyGrid die Eingabe eines Users auf ungültige Zeichen überprüfen. Wenn nach der Eingabe ungültige Zeichen enthalten sind, soll die Eingabe nicht übernommen werden und das betroffene Eingabefeld (nach einer Meldung) wieder in den "Edit-Modus" versetzt werden (mit blinkendem Cursor, ählich wie beim Label-Edit eines TreeView-Knotens).

Bis jetzt habe ich das als Teilproblem über den PropertyValueChanged-Event gelöst. So kann ich die Eingabe validieren. Jedoch weiß ich nicht wie ich das Value-Feld des GritItems ansprechen kann, so dass es in einen "Edit-Modus" versetzt werden kann (so, als hätte man das Feld angeklickt).

Hat jemand eine Idee wie man das macht?

Gruß
xbredoillex

18.09.2009 - 15:23 Uhr

So jetzt klappt es über das Event.

Danke euch.

18.09.2009 - 15:06 Uhr

Genau das habe ich gerade ausprobiert. Der Event heißt "AfterLabelEdit". Das bringt aber auch (merkwürdige) Probleme, die ich nicht mal nachvollziehen kann.

Ich weiß jetzt nicht ob ich dafür nicht einen neuen Thread eröffnen soll, oder doch lieber hierher?

18.09.2009 - 14:56 Uhr

Das habe ich mir fast gedacht, hoffe aber immer noch auf einen genialen Lösungsvorschlag 😃.

18.09.2009 - 13:24 Uhr

Hallo,

ich habe ein Treeview, welches mit erweiterten TreeNodes arbeitet. Das funktioniert auch super.

Nun möchte ich die Text-Eigenschaft mein Versuch sah so aus:


public void ErweiterterTreeNode() : TreeNode
{

	// Erweiterungen...

    public override string Text
	{
    	get{
    		return base.Text;
    	}
    	set{
			base.Text = value;
			aclass.aproperty = value;
    	}
    }
}

Es kommt jedoch die Fehlermeldung das diese Eigenschaft in der Basisklasse nicht überschreibbar ist ( "Basisklasse nicht als virtual, abstract oder override markiert").

Wenn ich das Schlüsselwort "new" verwende haben die Knoten im Treeview zur Laufzeit keine Labels mehr (nur Leerstring) .

Hat jemand eine Idee wie man das lösen könnte?

Gruß

10.09.2009 - 16:33 Uhr

Hi,

um meine Anwendung pluginfähig zu gestalten verwende ich den SharpDevelop Kern.

Als Vorlage diente das Testprojekt aus [Artikelserie] Den SharpDevelop Kern in eigenen Anwendungen verwenden.

Im Base-Projekt wird ein Dockpanel (WeifenLuo) im Hauptfenster (Workbench) erzeugt. Darin sollen über AddIns dockbare Panels erzeugt werden (bei SharpDevelop heißen diese Pads, glaube ich).

Nach Recherchen in http://www.codeproject.com/KB/cs/ICSharpCodeCore.aspx und http://www.codeproject.com/KB/cs/LineCounterSDAddIn.aspx denke ich, der Zugriff der AddIns auf das DockPanel muss über Doozer ermöglicht werden.

Zwar habe ich das Prinzip mit den Doozern und dem AddInTree verstanden, dennoch gibt es Unklarheiten. Die Aufrufe von Classes im AddInTree haben sich mir noch nicht so richtig erschlossen. Die einfachen Codebeispiele die ich dazu gefunden habe verstehe ich, diese verwenden jedoch nur das MenuService. Die Beispiele im Quellcode von SharpDevelop (version 2) sind für mich zu komplex und zu verschachtelt. Mein Problem liegt irgendwo dazwischen 😃.

Auch bin ich mir speziell bei der Pad-Geschichte beim Codeaufbau sehr unsicher. Zwei Möglichkeiten sind mir eingefallen:

  1. Einen Dockingfenster-Inhalt an eine Methode der Workbench schicken und damit das Dockfenster aus der Workbenchinstanz heraus erzeugen
  2. Das Dockingfenster direkt im AddIn erzeugen und von "außerhalb" an das DockPanel hängen.

Wie auch immer, ich komme bei beiden Möglichkeiten nicht weiter.
Kann mir jemand beim Konzept helfen und vielleicht in groben Zügen dazu die Implementierung über die Doozer erklären (speziell der eigentliche Aufruf des Panels)?

12.08.2009 - 14:01 Uhr

@ErfinderDesRades: Kein Problem =)

@Khalid: Dein Projekt funktioniert bei mir nicht, aber ich habe die Daten manuell übernommen und es geht jetzt 👍 😁

Des Rätsels Lösung scheint das Mdi-Gedöns zu sein. Ich habe es raus geschmissen und jetzt klappt alles, jedenfalls bisher 😉.

Was ich nicht verstehe: Im TestProjekt der Source von WeifenLuo ist aber trotzdem IsMdiContainer auf true gesetzt und er Arbeitet mit MdiChilds/Parents usw. 8o ?( 🤔

Vielen Dank an alle.
Liebe Grüße
xbredoillex

12.08.2009 - 11:49 Uhr

Vielen Dank für den Code! Werde ich heute nachmittag alles durchchecken.
Wusste gar nicht das das Dockpanel ohne Mdi-Zeugs geht. Habe mich da auf die Tutorials verlassen.

@ Erfinder des Rades:
Hatte dir gleich nach deinem Post geantwortet, dass dies irgendwie nicht geht, erst den MDI zu setzen und dann Show anzuzeigen, weil dann die besagte Fehlermeldung kommt. Oder Meinst du etwas anderes?

12.08.2009 - 11:11 Uhr

Hi Khalid,

du siehst die Spuren meiner wilden Experimente. Ich brauche jetzt wohl nicht mehr zu erwähnen, dass ich Anfänger bin 😄
Das Beispiel ziehe ich mir grad rein, ist aber relativ kompliziert und verschachtelt.

Folgendes zu deinen Vorschlägen:

Wenn ich folgendes tue:*Ich erstelle ein neues Projekt mit einem Menu + DockPanel auf Form1 und einem leeren Form2. *In Form1 setze ich das Property IsMdiParent auf true. *Im Form2 ändere ich die Ableitung von "Form" auf "DockContent". *Auf Form2 ziehe ich ein TreeView-Element von der Toolbox und setze es auf Fill. *In Form1 schreibe ich in den MenuButtonKlickEvent folgende Zeilen:


private void ButtonToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.Show(dockPanel1, DockState.DockLeft);
            form2.MdiParent = this;        
        } 
    }

Wenn ich das alles so mache, kommt exakt das Problem aus dem Startbeitrag. Das TreeView wird erst im zweiten Anlauf angezeigt (siehe Screenshots).

Siehst du oder jemand anderes da irgendwo einen (systematischen) Fehler den ich mache? Ich würde gerne ausschließen das es an mir oder meiner IDE liegt.

Es wäre super wenn sich jemand der die dockpanel.dll schon hat, ein paar Minuten Zeit nimmt und schaut, ob der Fehler reproduzierbar ist.

Viele Grüße
xbredoillex

12.08.2009 - 10:24 Uhr

Hallo ErfinderDesRades,

Ich habe das Tree jetzt in den Form2 veschoben, es wird nun aber gar nicht mehr angezeigt, nur das Panel erscheint:


// Das Parent------------------------------------------
using WeifenLuo.WinFormsUI.Docking;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void ButtonToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.Show(dockPanel1, DockState.DockLeft);
            form2.MdiParent = this;
        } 
    }
}

// Das Child------------------------------------------
using WeifenLuo.WinFormsUI.Docking;

namespace WindowsFormsApplication1
{
    public partial class Form2 : DockContent
    {
        public Form2()
        {
            InitializeComponent();
            MakeTree();  
        }

        public void MakeTree()
        {
            TreeView treeView1 = new TreeView();   
            treeView1.Dock = DockStyle.Fill;

            Form1 Parent = new Form1();
            (Parent as Form1).dockPanel1.Controls.Add(treeView1);
        }
    }
}

Wenn ich dich richtig verstanden habe, sollte ich im Parent folgendeReihenfolge einhalten:


//statt dieser:  
form2.Show(dockPanel1, DockState.DockLeft);
form2.MdiParent = this;

//diese hier:
form2.MdiParent = this;
form2.Show(dockPanel1, DockState.DockLeft);

Das geht leider nicht. Alle versuche das MDIParent vor dem Show zu setzen scheiterten mit der Fehlermeldung:


"Invalid Content: ActiveContent must be one of the visible contents, or null if there is no visible content."

Selbst wenn ich mit dem minimal möglichen Code das blanke Child anzeigen lassen will.

Die Fehlermeldung hatten andere auch schon, es sind keine Lösungsansätze zu finden.

12.08.2009 - 00:23 Uhr

JA das dachte ich mir auch, das Child verhält sich auch komisch. Wenn der Pin umgekippt ist, dann bleibt es trotzdem ausgefahren und fährt nicht automatisch rein.

Aber es kann doch nicht sein das ich der erste bin, der dieses Problem hat?

12.08.2009 - 00:02 Uhr

Auf Bild2 sieht man dann das Childfenster mit dem weißen (noch leeren) Tree, nachdem man das Childfenster einmal ein- und wieder ausgeklappt hat.

Es spielt keine Rolle ob der Tree gefüllt ist oder nicht, das Problem tritt immer auf. Wie gesagt, bei Float oder Dokument erscheint der Tree mit dem ersten Auftauchen des Childfensters, bei DockLeft/Right etc erscheint der Tree erst nachdem mal das Childfenster einmal ein und ausgeklappt hat, was ziemlich unschön ist, da nicht erwünscht.

11.08.2009 - 23:57 Uhr

Ich habe mal Screenshots gemacht die das Problem zeigen.

Auf Bild1 sieht man das Childfenster wie es zunächst erscheint, wenn man im Menu auf child klickt.

11.08.2009 - 23:33 Uhr

Danke für die schnelle Antwort.
Der Tree soll ja erst nach dem Knopfdruck kommen und nicht beim Formload.
Beim Klick kommt das Childpanel sofort, aber es ist leer. Erst wenn ich einklappe und dann wieder aufklappe ist der Tree da. Der Tree soll aber sofort mit dem Child erscheinen. Oder habe ich dich jetzt falsch verstanden? 😃

11.08.2009 - 23:04 Uhr

Hi,

ich verwende die Dockpanel Suite.
Es wird ein Childfenster erzeugt, mit einem Treeview gefüllt mit DockState.DockLeft an den linken Rand gedockt.

Problem ist, dass beim Erzeugen des Dockfensters der Treeview nicht zu sehen ist. Ich muss erst einmal auf die "Pinnadel" klicken und das Dockpanel einzuklappen, beim erneuten Aufklappen ist der Treeview sichtbar.
Wenn ich das Fenster als Float oder Document erzeuge ist der Treeview sofort zu sehen.

Wie kann ich es bewerkstelligen, dass das Fenster angedockt erscheint und der Treeview von Anfang an zu sehen ist?

Im Anhang ist der Code zum Problem.

Viele Grüße
xbredoillex

Das Mainform:



using WeifenLuo.WinFormsUI.Docking;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void ButtonToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeView treeView1 = new TreeView();
            treeView1.Dock = DockStyle.Fill;

            Form2 form2 = new Form2();
            form2.Controls.Add(treeView1);
            form2.Show(dockPanel1, DockState.DockLeft);
            form2.MdiParent = this;
        }
    }
}

Das Childfenster:



using WeifenLuo.WinFormsUI.Docking;

namespace WindowsFormsApplication1
{
    public partial class Form2 : DockContent
    {
        public Form2()
        {
            InitializeComponent();
        }
    }
}

08.08.2009 - 10:45 Uhr

Hallo herbivore, danke für deine Antwort.

Es klappt jetzt mit dem DockingPanel. 👍 😁

Dein Hinweis wegen dem "IsMdiContainer=true" hat mich dazu gebracht an dieser Stelle näher nachzuschauen. Das war der richtige Anstoss.

Und zwar muss die Eigenschaft auf true stehen. Mein Fehler war, dass ich, vor dem Aufruf des Child (Form2), diesem nicht das MdiParent mitgeteilhabe habe.

Der Button war logischerwiese vom Panel verdeckt. Ich habe ihn jetzt durch ein ToolStripMenu ersetzt.

Es muss in Form1 heißen:



using WeifenLuo.WinFormsUI.Docking;

namespace DockPanelTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void KLICKMICH_ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.MdiParent = this;
            form2.Show(dockPanel1);
        }
    }
}


Schönes Wochenende,
xbredoillex

07.08.2009 - 18:44 Uhr

Hallo,

ich hoffe ich nerve nicht, aber ich wollte dieses Wochenende programmieren und scheitere und verzweifle an diesem DockPanel. Und da ich mich in die Optik und Funktionalität verliebt habe, möchte ich es uuuunbedingt haben. 😉

Alle Versuche heute sind wieder gescheitert ein ChildForm im DockPanel zu öffnen. Es geht einfach keines auf. Irgendwie bewege ich mich im Kreis. Was mich stutzig macht ist, dass der Button auf dem HauptForm in der Designansicht zu sehen ist, beim Starten des Programms wird er aber vom DockPanel verdeckt. 🙁

Hat denn keiner eine Idee? Vielleicht einen Link mit einem Tutorial oder einen Snippet oder ein TestProjekt oder sowas für c#?

Sofern alles andere richtig ist kann es doch nur an dem Aufruf des Childs im button_click liegen, oder? 🤔

Liebe Grüße
xbredoillex

06.08.2009 - 18:51 Uhr

Hi,

wie ich bereits erwähnte werde ich aus den Anleitungen nicht schlau.
Die Doku die bei http://sourceforge.net/projects/dockpanelsuite/ dem Projekt beigefügt ist beschreibt die Features und die Hierarchien der Fenster, sie enthält jedoch keine Codebeispiele, Tutorials oder ähnliches.

Es gibt auch ein Tutorial für VB, damit kann ich aber mangels Erfahrung leider nichts anfangen. Da müsste ich mich erst in VB einarbeiten um als C#-Anfänger ein C# Problem zu lösen 😃.
Bei codeproject.com war mal das Original Projekt von Weifen Luo, dieses ist aber vor einigen Monaten wieder von der Seite genommen worden.

Die Bedeutung der Fehlermeldung kenne ich, ich weiß nur nicht wie ich das DockPanel ansprechen soll.
Die erwähnte Stelle mit der Fehlermeldung habe ich 1 zu 1 aus einem Beispiel übernommen (http://www.mrleeh.de/mrleeh/archives/21-Docking-Panel-Suite.html). Im Beispiel ist definitiv nur ein Parameter (der Name des DockingPanels) im Show() und der wird ja bei mir bemängelt.
Vielleicht kann mir jemand sagen ob es was mit der Vererbungsauswahl zu tun hat (Punkt 5 im Onlinebeispiel). Wie gesagt, in der Express-Version gibt es keine Vererbungsauswahl. Ich habe das im Startbeitrag erwähnt, auch wie ich es versucht habe zu lösen.

Kann jemand von euch das Beispiel mit VS C# 2008 Express zum Laufen bringen?

Ich will ja nur erstmal ein Fensterchen öffnen, das ist mein ganzes Problem, dann komme ich hoffentlich klar. 😃

06.08.2009 - 16:53 Uhr

Hi,
ich bekomme das DockPanel Suite einfach nicht zum laufen und hoffe auf Hilfe.

Ich bin bisher so vorgegangen:Ein neues Projekt ist angelegt (Visual C# 2008 Express Edition).1.Die DockPanel DLL ist eingebunden, das DockPanel ist in der Toolbox aufgeführt. 1.Beim Hauptformular Form1 ist die Eigenschaft "IsMdiContainer" auf true gesetzt. 1.Aus der Toolbox wurde ein DockPanel (dockPanel1) auf Form1 gezogen. 1.Die Eigenschaft "Dock" des DockPanels wurde auf fill gestellt, die Eigenschaft "DockingStyle" auf DockingMdi. 1.Auf Form1 wurde ein Button gezogen, der später beim Draufklicken das Childfenster im Panel öffnen soll

Leider sind alle (spärlichen) Anleitungen die ich gefunden habe für mich nicht umsetzbar. Die einen sind für c++, die einen für VB, und die die ich für c# gefunden habe, sind nicht ausreichend detailliert. Ab jetzt fangen die Probleme schon an 😃*In den Anleitungen wird immer ein neues Child-Fenster angelegt, und im Fenster "Vererbungsauswahl" etwas eingestellt.
PROBLEM: Ich habe die VS 2008 Express Edition, und dort gibt es kein Fenster "Vererbungsauswahl" oder inherit form, man kann kann nur ein neues Form erzeugen und sonst nichts. Recherchen ergaben das ich nicht der einzige mit dem Problem bin 😃.
PROBLEM: In der einen Anleitung steht man soll vom Hauptfenster erben, in einer anderen steht man soll von DockContent erben.
Zunächst habe ich einfach ein normales Form2 von Form1 beerben lassen. Dann habe ich die unten aufgeführte Methode verwendet.
Bei der Zweiten Methode wie im Code unten verändert sich das Designfenster von Form2, wird grau und zeigt einen Text der einem sagt, man solle Tools auf die Fläche ziehen. Das Formsymbol im Projektmappenexplorer verändert sich auch.

*Wenn ich das Programm starte geht immer das Hauptfenster auf, aber der Button den ich auf das Form1 gezogen habe ist nicht sichbar, vermutlich unterhalb des dunkelgrau erscheinenden Dockpanelhintergrundes. Mehr habe ich nicht hinbekommen ohne viele Fehlermeldungen zu generieren.

Folgendes habe ich versucht und liegt als Grundgerüst vor:

Hauptfenster:


using WeifenLuo.WinFormsUI.Docking;

namespace DockPanelTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 child = new Form2();
            child.Show(...xyz...);
        }
    }
}

Bei child.Show() habe ich für xyz in die Klammern auch Parameter wie in den Anleitungen eingetragen, diese haben aber Fehlermeldungen gebracht, dass die Parameteranzahl nicht stimmt.
[edit 2]: genaue Fehlermeldung bei


child.Show(dockPanel1);

ist: "Keine Überladung für die Show-Methode nimmt 1 Argumente an."
[/edit 2]

Childfenster:


using WeifenLuo.WinFormsUI.Docking;

namespace DockPanelTest
{
    public partial class Form2 : DockContent
    {
        public Form2()
        {
            InitializeComponent();
        }
    }
}

Ich hoffe das ist keine triviale Anfängerfrage. Vielleicht kann mir jemand mal irgendwie auf die Sprünge helfen?

Viele liebe Grüße
xbredoillex

[edit 1]: Zusatzinfo bei 4. eingetragen, dass "DockingStyle" auf DockingMdi gestellt ist. [/edit 1]