Laden...
Avatar #avatar-3071.jpg
TripleX myCSharp.de - Member
Student Nürtingen Dabei seit 30.09.2006 328 Beiträge
Benutzerbeschreibung

Forenbeiträge von TripleX Ingesamt 328 Beiträge

26.01.2010 - 01:25 Uhr

sieht sehr gut aus 👍

Ich hätte aber noch ein paar Verbesserungsvorschläge:

  • In der Projektansicht steht ja ganz oben: Projekt"test" aufgaben. Dadrnter gibts nomal ne Zeile, wo steht Projekt erstell am ... im ersten Wort fehlt ein k

-wenn ich eine neue Aufgabe einfüge, ist die neue Zeile nur halb gehighlightened.

  • Was ich auch unschön finde ist die Vermischung von englischem und deutschen Text.

  • Dass Enddatum einer Aufgabe darf kleiner sein als das Startdatum ?

  • ein löschen-button bei den Prioritäten wäre ganz nett

  • Wie kann ich Anhänge anschauen / einzeln löschen? (ok habs rausgefunden, hat aber ein wenig gedauert *g)

  • auf einmal waren alle aufgaben, die ich eingetragen waren weg (bis auf einen). beim beenden und neu laden des Projektes waren sie aber wieder drin. weiß aber leider net wie ich es geschafft habe ...

  • wenn ich einen status erstelle und einer Aufgabe diesen Status zuweise und ich lösce den status dann wieder, dann ist der Status direkt auf erledigt. Besser wärs meiner Meinung den Status leer zu lassen und ne Fehlermeldung (in form eines roten Rahmens, Ausrufezeichen, ...) anzuzeigen

  • bei der priorität das gleiche wie oben.

20.01.2010 - 23:31 Uhr

Im Setter von

public double dDNumthree  

wird der value Parameter nicht verwendet. Das kann zwar gewollt sein, ist es aber in 99.999% der Fälle nicht.

und ich glaube nicht dass er zu den 0,001 % gehört 😃 folgendes sollte ausreichend sein:

public double dDNumthree
        {
            get
            {
                return DNumone + DNumtwo;
            }
        }

dann kann man

        public double result()
        {
            return dDNumthree;
        }

noch löschen, denn die braucht man nicht.

Ausserdem kannst du anstatt ne private Variable zu erstellen und diese dann zu kapseln doch direkt die "normalen" Properties verwenden. "Aufgeräumt" würde der Code dan so aussehen:


public double dDNumOne { get; set }
public double dDNumTwo { get; set }
public double dDNumThree { get { return dDNumOne + dDNumTwo; }

public double Add(double value1, double value2)
{
            return value1 + value2;
}
}

ist aber alles etwas unschön, ich würde die properties ganz weglassen ... und nur die add() Methode anbieten.

MfG TripleX

20.01.2010 - 22:38 Uhr

das u.a. Aussehen der Textbox festlegt.

Dafür gibt es in WPF doch styles

Aber das DataContext erlaubt doch nur ein Object als Quelle

Er meinte das anders, und zwar gib der TextBox einen Namen (z.B. txtInput), dann kannst du im code behind darauf zugreifen mittels txtInput.Text = "Hello World". Oder um eine Datenbindung im CodeBehind zu erstellen, kannst du dann acuh folgendes machen:

Binding binding = new Binding();
binding.Source = Zaehler;
txtInput.SetBinding(TextBlock.TextProperty, binding);

Und mit MVVMPatterns habe ich mich nie beschäftigt.

Solltest du mal tun, ist en ganz nettes Pattern für WPF-Anwendungen

20.01.2010 - 22:30 Uhr

btw, ich würde dir empfehlen, Properties groß zu schreiben (ist nämlich Standard in C#):

public string InfoText
    {
        get { return _infoText; }
        set
        {
            _infoText = value;
            OnPropertyChanged("InfoText");
        }
    }

MfG TripleX

20.01.2010 - 22:27 Uhr

ich verstehe nicht was dich daran hindert, im Konstruktors des CodeBehinds folgendes zu schreiben:

DataContext = this;

?

MfG TripleX

19.01.2010 - 12:22 Uhr

Das was talla schon sagt beschreibt dein Problem ... wenn du immer mit dem gleichen Object arbeitest ändern sich auch die Werte in der Liste. Du könntest jetzt um das verhalten vorzubeugen das gewünschte Object wie folgt klonen:

            int[] co = { 1, 2, 3, 4 };
            int[] co2 = (int[])co.Clone();

            test.Add(co);

            for (int i = 0; i < co2.Length; i++)
            {
                co2[i] = i + 10;
            }

            test.Add(co2);

habe es jetzt so gelöst, obwohl ich die lsg. irgendwie nicht schön finde!

ih finde den Quellcode auch sehr unschön mit den ganzen if-bedingungen und for-schleifen. Kannst du keine Teile auslagern in eine extra Funktion? Oder speicher, um den code etwas lesbarer zu machen wenigstens folgende Variable zwischen:

gv.Lastfall[LFNr].schrittNummer[schrittNummer].Stuetzen

also ich würde ganz oben über der erste forschleife schreiben:

var guterName = gv.Lastfall[LFNr].schrittNummer[schrittNummer].Stuetzen

var und guterName sollten natürlich durch etwas sinnvolles ersetzt werden.

19.01.2010 - 02:21 Uhr

Die Schleifen können problemlos in einer beliebigen Reihenfolge fertig werden, jedoch soll url1 immer vor url2 im Thread aufgerufen werden und nicht umgedreht:

Also du hast in deinem jetzigen post eine schleife und in dieser schleife erstellst du einen Thread der eine Methode aufruft. Diese Methode wird sequentiell vom Thread abgearbeitet, dass heißt getHTML(1) wird vor getHTML(2) aufgerufen.

Ich glaube in deiner vorherigen Lösung war es andersherum - da hattest du eine schleife wo du einen Thread erstellt hast welche dann die gethtml(i) (wobei i in der schleife jedesmal variiert). Das heißt du erzeugst einen Thread für getHTML(1) und direkt danach einen Thread getHTML(2). Da wird das nix mit sequenzielle Abarbeitung dank deinem Betriebssystem 😉

€dit: Sry hab falsch geschaut, in deiner letzten Lösung hattest ja die selbe Schleife.
Hm dann könnte es meiner Meinung nur noch dran liegen dass du in den getHTML Methoden wiederrum einen Thread startest, der dir zum Beispiel den Quellcode holt. Dann wird die zweite GETHML anweisung aufgerufen welche schneller fertig ist als die erste?

19.01.2010 - 02:05 Uhr

dann bist da aber den falschen Weg gegangen. In der Schleife erstellt du immer wieder einen neuen Thread, und welcher Thread von den ganzen nun zuerst fertig wird bzw abgearbeitet wird ist unterschiedlich.

Wenn du willst dass zwar mehrere Schleifen parallel abgearbeitet werden, die schleife jedoch sequentiell dann erstelle einen Thread für jede schleife.

Der Thread ruft dann eine Methode auf, wo die Schleife drin ist. Das lässt sich ganz gut mit Anonymen Methoden lösen. Dazu mal ein kurzes Beispiel:

            Thread[] thrd = new Thread[2];
            for (int i = 0; i < thrd.Length; i++)
			{
                thrd[i] = new Thread(new ThreadStart(() => {
                    for(int j = 0; j < 1000; j++) {
                        Console.WriteLine(Thread.CurrentThread.Name + " ... " +j);
                    }
                }));
                thrd[i].Name = "Thread "+i;
                thrd[i].Start();
			}

MfG TripleX

19.01.2010 - 01:54 Uhr

ich würde den Pfad folgendermaßen aufbauen:

String sExe = Path.Combine(Application.StartupPath , "Ordner/Ordner/Ordner/start.exe")

Wozu nimmst die Path.Combine Methode wenn du sie nicht ganz ausschöpfst?
Besser wäre es folgendermaßen:

Path.Combine(Application.StartupPath, "Ordner", "Ordner", Ordner", "start.exe")

MfG TripleX

19.01.2010 - 01:47 Uhr

...und lies ihn dann über Match.Groups[1] aus.

magic numbers X(
besser ist folgendes:

(?<Name>(*.?)) 

Dann kann man mittels Match.Groups["Name"].Value auf den Wert zugreifen 😉

17.01.2010 - 00:56 Uhr

Vielen Dank für deinen tollen Artikel, hab wieder einiges gelernt. 👍

Ich werde jetzt auch noch etwas zu deinem Artikel beitragen, denn ich denke dass das ganz gut hier herein passt:
Es kommt oft vor, dass eine Property von einer anderen abhängig ist. Wenn man also die eine Property ändert, ändert sich automatisch eine andere Property. Am besten ich zeige mal ein kurzes Beispiel:

public class TestClass : INotifyPropertyChanged
    {
        private int _width;
        private int _height;

        public int Height
        {
            get { return _height; }
            set { _height = value; NotifyPropertyChanged(MethodInfo.GetCurrentMethod()); }
        }

        public int Width
        {
            get { return _width; }
            set { _width = value; NotifyPropertyChanged(MethodInfo.GetCurrentMethod()); }
        }

        public int Area
        {
            get { return Height * Width; }
        }

Wie man erkennen kann ist Area von _Height _und _Width _abhängig. Also eigentlich müsste man, sobald man _Width _geändert, bekanntgegeben werden dass sich _Area _geändert hat. Ich habe mich demletzt mit diesem Problem auseinander gesetzt und bin dabei auf 2 Lösungen gekommen:

1. Die einfache Variante:
Man ändert die Setter der jeweiligen Properties folgendermaßen um:

        public int Height
        {
            get { return _height; }
            set
            {
                _height = value;
                NotifyPropertyChanged(MethodInfo.GetCurrentMethod());
                NotifyPropertyChanged("Area");
            }
        }

        public int Width
        {
            get { return _width; }
            set
            {
                _width = value;
                NotifyPropertyChanged(MethodInfo.GetCurrentMethod());
                NotifyPropertyChanged("Area");
            }
        }

        public int Area
        {
            get { return Height * Width; }
        }

Also sobald sich _Width _oder _Height _ändert, wird auch bekanntgegeben dass _Area _sich geändert hat.
Dass Problem bzw. unschöne an dieser Variante ist meiner Meinung jedoch, dass _Width _ eigentlich gar nichts von Area wissen sollte. Denn wenn wir aus irgendeinem Grund die Area nicht mehr brauchen und entfernen würden, dann sollten wir den Aufruf der NotifypropertyChanged() aus _Width _und Height auch entfernen (was man leicht vergessen kann). Außrdem kann es vorkommen, dass man mehrere Properties hat, welche von _Width _abhängig sind, und dann würden wir den setter nur unnötig aufblasen.

2. Die schönere Variante (mittels Attribute):
Die Nachteile aus Variante 1 löst man, indem man Attribute verwendet. Ich zeige euch mal einen Codeausschnitt, der das gleiche Ziel wie in Variante 1 verfolgt:

public int Height
        {
            get { return _height; }
            set { _height = value; NotifyPropertyChanged(MethodInfo.GetCurrentMethod()); }
        }

        public int Width
        {
            get { return _width; }
            set { _width = value; NotifyPropertyChanged(MethodInfo.GetCurrentMethod()); }
        }

        [DependsUpon("Height", "Width")]
        public int Area
        {
            get { return Height * Width; }
        }

Wie man erkennen kann hat _Area _jetzt ein Attribut erhalten. Mittels _DependsUpon _wird jetzt gesagt, dass Area von _Width _und Height abhängig ist. Sobald sich _Width _oder _Height _ändert wird automatisch auch das Event für _Area _gefeuert. Da dass aber nicht automatisch passiert brauchen wir noch ein wenig mehr Code. Hier ist ersmal der Code für das Attribut:

[global::System.AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
    sealed class DependsUponAttribute : Attribute
    {
        #region Private Members
        private readonly string[] _properties;
        #endregion

        #region Public Properties
        public string[] Properties
        {
            get { return _properties; }
        }
        #endregion

        #region Constructors
        public DependsUponAttribute(params string[] properties)
        {
            this._properties = properties;
        }
        #endregion
    }

Und hier ist die gesamt Klasse für das obige Beispiel:

public class TestClass : INotifyPropertyChanged
    {
        private Dictionary<string, string[]> _propertyDependencies;

        private int _width;
        private int _height;

        public int Height
        {
            get { return _height; }
            set { _height = value; NotifyPropertyChanged(MethodInfo.GetCurrentMethod()); }
        }

        public int Width
        {
            get { return _width; }
            set { _width = value; NotifyPropertyChanged(MethodInfo.GetCurrentMethod()); }
        }

        [DependsUpon("Height", "Width")]
        public int Area
        {
            get { return Height * Width; }
        }

        public TestClass()
        {
            #region Save depend Properties in the dictionary
            _propertyDependencies = new Dictionary<string, string[]>();

            foreach (var item in this.GetType().GetProperties())
            {
                var query = (from prop in this.GetType().GetProperties()
                             where prop.GetCustomAttributes(typeof(DependsUponAttribute), false)
                                       .Cast<DependsUponAttribute>()
                                       .Any((x) => x.Properties.Any((y) => y == item.Name))
                             select prop.Name).ToArray<string>();
                if (query.Count() > 0)
                {
                    _propertyDependencies.Add(item.Name, query);
                }

            }
            #endregion
        }


        #region INotifyPropertyChanged Implementation (+ Notify Dependend Properties)

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

            #region Notify other Properties
            if(_propertyDependencies.ContainsKey(propertyName))
            {
                string[] depended = _propertyDependencies[propertyName];
                foreach (var propName in depended) NotifyPropertyChanged(propName);
            }
            #endregion
        }
        public void NotifyPropertyChanged(System.Reflection.MethodBase methodBase)
        {
            NotifyPropertyChanged(methodBase.Name.Substring(4));
        }
        #endregion
    }

Im Konstruktor der Klasse werden die Abhängigkeiten der Properties untereinander ermittelt und in eine Dictionary abgespeichert.
Sobald sich jetzt eine Property ändert, wird in NotifyPropertyChanged ersteinmal das event abgefeuert und danach wird in der Dictionary geschaut, ob für das Properties Abhängigkeiten bestehen und für jene wird dann auch eine Benachrichtigung gesendet.

Fazit:

  • Die zweite Variante ist zwar langsamer und braucht auch mehr Overhead als die erste, doch man sieht viel schneller welche Eigenschaften voneinander abhängig sind. Außerdem ist es für mich logischer, dass Width gar nicht weiß dass Area von ihr abhängig ist.
  • Das Problem mit den sog. "Magic Strings" ist leider bei beiden varianten vorhanden. Dadurch kann es Probleme beim Refactoring geben.

MfG TripleX

15.01.2010 - 23:07 Uhr

natürlich kannst du auf die Elemente zugreifen, du kannst ja z.B. mittels textBoxStart.Text = "Dummy" irgendeinen Text festlegen. Also ich verstehe nicht ganz wo du drauf hinaus willst.

Btw ich denke mal, dass du in den TabPages nicht nur eine TextBox anzeigen lassen willst, sondern es werden bestimmt mehrere Objekte sein, du du pro TabPage anzeigen lassen willst. Dann würde ich an deiner Stelle ein neues UserControl erstellen welches dann so aussehen soll wie du es willst. Dieses UserControl musst du dann nur noch später in ein Tab hinzufügen und kannst über Properties (welche du vorher natürlich implementiert haben musst) das verhalten bzw. Aussehen des UserControls beeinflussen.

MfG TripleX

15.01.2010 - 22:34 Uhr

Hallo Fiech,

also wenn ich dich richtig verstanden habe, weisst du erst ab Programmstart wieviele Netzwerkkarten im PC eingebaut sind (klingt logisch 😉 ). Jetzt möchtest du jenachdem wieviele Netzwerkkarten vorhanden sind, TextBoxen anzeigen lassen.

Nun also du könntest zum Beispiel sobald du eine Netzwerkkarte gefunden hast, mittels ParentControl.Controls.Add() eine neue TextBox hinzufügen. ParentControl ist das Control, wo deine TextBoxen angezeigt werden, z.B. eine GroupBox.

MfG TripleX

15.01.2010 - 19:59 Uhr

verwendetes Datenbanksystem: Sql Server Compact Edition 3.5
verwendetes Programmierumgebung: Visual Studio 2010 Beta 2

Hallo Gemeinde,
Ich habe seit kurzem die UnitTests für mich entdeckt und wollte damit jetzt ein paar meiner Klassen testen. Dazu wollte ich den UnitTest mit einer Datenbank verbinden, damit er die Werte, welche erz um Testen benötigt, aus einer Datenbank holt. Ich hätte nicht gedacht dass ich mich mehrere Stunden rumärgern und rumprobieren darf - bis dass ganze (nicht ...) funktioniert.

Also hier ist mal eine kure Beschreibung was ich bisher gemacht habe:

  • Bei der zu testenden Klasse in Visual Studio rechtsklicken und "Create Test" ausgewählt. (es wurde ein neues TestProjekt und eine Testklasse erstellt)
  • Eine Lokale Datenbank erstellt und eine Tabelle
  • In der TestKlasse habe ich bei der Funktion, welche getestet werden soll folgendes geschrieben (Pfad zur Datenbank gekürzt):
        [TestMethod()]
        [DataSource(@"Provider=System.Data.SqlServerCe.3.5;Data Source=(pfad)\TestDatabase.sdf"
            , "LengthValidationTest")]
        public void MaxLengthTest() //..

Wenn ich jetzt den Test starten bringt mir VS eine Fehlermeldung:

The unit test adapter failed to connect to the data source or to read the data. For more information on troubleshooting this error, see "Troubleshooting Data-Driven Unit Tests" (
>
) in the MSDN Library.
Error details: The 'System.Data.SqlServerCe.3.5' provider is not registered on the local machine.

Ich habe jetzt schon die ganze Zeit rumprobiert, doch es will einfach nicht funktionieren. Im Netz habe ich bereits auch mehrfach nach einer Lösung gesucht doch ich konnte nichts verwertbares finden.

Kann mir wer behilflich sein??

€dit: Problem gelöst, ich hatte den falschen Provider angegeben und dass obwohl ich den obigen Provider auf den MSDN Seiten vorgeschlagen wurde -.-). Der korrekte Provider lautet: Provider=Microsoft.SQLSERVER.CE.OLEDB.3.5.

14.01.2010 - 19:21 Uhr

Hallo, gestern bin ich auf Sandcastle und die GUI sandcastle Help File Builder gestoßen und finde es ein gutes Tool um Help-Files zu erstellen. Doch leider habe ich ein Problem und zwar will er mir manche Funktionen einfach nicht in die .chm Datei einbinden:

Konkret gehts um folgende Funktionen (es gibt bestimmt noch mehr, aber ber der Klasse ist es mir halt aufgefallen):

//siehe edit weiter unten

Hab schon alles mögliche versucht damit diese Funktionen auch aufgelistet werden, aber es klapt einfach nicht. Hat vielleicht von euch jemand ne Idee woran dass liegt?

€dit: also das Problem konnte ich eingrenzen auf die unten angegebene Methode. Sobald ich diese auskommentiere wird die Hilfe zu dieser Klasse, mit allen ihren funktionen und members korrekt angezeigt:

protected virtual Dictionary<string, object> GetPropertyValues()
        {
            var dict = (from pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
                        where pi.CanRead == true && pi.CanWrite == true
                        select pi).ToDictionary(x => x.Name, x => x.GetValue(this, null));
            return dict;
        }

€dit 2: hab den Bug jetzt weiter eingegrenzt:


            var dict = this.GetType()
                           .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
//                           .Where(x => (x.CanRead && x.CanWrite))
//                           .ToDictionary(x => x.Name, x => x.GetValue(this, null));

wenn ich die Zeile mit Where() auskommentiere, tritt der oben genannte Bug auf. Jetzt verwende ich halt erstmal folgendes Workaround:

            Dictionary<string, object> dict = new Dictionary<string, object>();
            var propertyInfos = this.GetType()
                                    .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
            foreach (var item in propertyInfos)
            {
                if (item.CanRead && item.CanWrite)
                    dict.Add(item.Name, item.GetValue(this, null)); ;
            }

Ich poste dass nur damit falls jemand das gleiche Problem wie ich haben sollte sich nicht den ganzen Tag auf Fehlersuche begibt 😉

14.01.2010 - 02:53 Uhr

Habe das Forum durchsucht und m.E. sogar fast die gleiche Frage einmal gefunden, die Antwort bringt mich aber so garnicht weiter irgendwie..

bist bestimmt auf "meinen" Thread gestoßen, denn ich hatte dem letzt die selbe frage
. Also ich habe das Problem so gelöst, das ich meine ganzen Daten in eine lokale SQL Datenbank gepackt habe und danach dass Ganze mittels Linq2Sql gemapped habe (das sind dann meine Models).

Wenn ich jetzt die Daten einer Tabelle aus der Db anzeigen möchte, erstelle ich ebenfalls wie du eine ObservableCollection (was ich aber glaube ich gar net mal brauche, ich könnte auch eine normale List verwenden?):

        public ObservableCollection<NetworkDrive> NetworkDrives
        {
            get
            {
                if (_networkDrives == null)
                {
                    _networkDrives = new ObservableCollection<NetworkDrive>();
                    var query = _db.NetworkDrives;
                    foreach (var item in query) _networkDrives.Add(item);
                }
                return _networkDrives;
            }
        }

Der unterschied ist, dass ich eine if() abfrage in meinem getter habe und diese Daten erstmal zwischenspeichere, dadurch wird "nicht einfach eine neue ObservableCollection erzeugt". Aber ganz gelöst habe ich glaub das Problem noch nicht, denn wenn ich im Code eine neue Zeile hinzufügen wird diese nicht automatisch hinzugefügt. Hab das aber nicht getestet da dass bei mir sowieso nicht vorkommt. Aber dafür werde ich bestimmt auch noch eine Lösung finden, da ich aber gerade in "Prüfungsstreß" bin, habe ich keine zeit um weiter an das Projekt weiter zu arbeiten.

Aber dadurch, dass ich die Tabellen mit Linq2SQL gemapped habe, ist die Datenbank an die Collection gebunden und wenn ich in einer DataGrid einen Wert ändere, wird er auch in der Datenbank gespeichert (natürlich erst, wenn .SubmitChanges() aufgerufen wird). Gleiches gilt fürs löschen oder hinzufügen einer neuen Zeile.

Wie man es aber ohne Datenbank und Linq2SQL macht, weiss ich gerade auch nicht. Ich **denke **man muss da dann wirklich für jede Operation (Add, Remove, ...) in der ModelSchicht eine Funktion anbieten, und die ModelSchicht muss Änderungen immer mittels INotifyChanged bekanntgeben (sollte klar sein).

Ich hoffe ich konnte dir ein wenig auf die Sprünge helfen, wenn nicht einfach warten bis sich ein kompetenterer user meldet 😃

13.01.2010 - 17:22 Uhr

Halo Gemeinde,

gestern bin ich auf dieses Projekt (auch bei codeplex vorhanden) aufmerksam geworden. Da ich es aber gerade nicht verwenden bzw. testen kann wollte ich mal fragen ob ihr damit schon Erfahrungen gemacht habt.

Prinzipiell würde ich sagen, dass die Idee hinter dem Projekt sehr gut ist - oder gibts vielleicht irgendwelche Nachteile?

13.01.2010 - 11:28 Uhr

da wäre es dann vielleicht dass sinnvollste, im Konstruktor die Checksumme zu errechnen und in eine Variable abzuspeichern. Im Destruktor dann nochmal die Checksumme errechnen und dann je nachdem das Objekt zu speichern.

Das Problem was ich aber da gerade sehe ist, dass wenn ich die Checksumme im Konstruktor errechne und speichere, die Checksumme des Objekt dadurch ja wiederrum geändert wird?

13.01.2010 - 11:01 Uhr

Du könntest zum Beispiel in deinem Objekt bei jeder Property Änderungen mittels INotifyPropertyChanged bekannt machen.

z.B.


public class TestClass : INotifyPropertyChanged
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                if (!value.Equals(_name))
                {
                    _name = value;
                    NotifyPropertyChanged("Name");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(String propertyName)
        {
            NotifyPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
        public void NotifyPropertyChanged(PropertyChangedEventArgs args)
        {
            //Hier eine Variable setzen, welche aussagt dass das Objekt geändert wurde.
            // ...
            if (PropertyChanged != null)
            {
                PropertyChanged(this, args);
            }
        }
}

Ich denke IEditableObject für die Klasse implementieren und beim EndEdit() speichern könnte das gewünschte sein.

Sollt ich mir mal

  1. du schreibst dir für das objekt eine "checksum" methode. diese summe merkst du dir intern im objekt. wenn es dann um das speichern geht, führst du die methode wieder aus und vergleichst sie mit der gemerkten. so weißt du das sich was geändert hat.

Die Idee gefällt mir auch ganz gut

MfG TripleX

13.01.2010 - 10:52 Uhr

Also ich würde dir auch empfehlen, Dateien die gerade geöffnet sind, nicht zu kopieren. Speicher die Dateien, welche gerade geöffnet sind in einer Liste und gib dem User bescheid dass die und die Dateien nicht gesichert werden konnten. Dann kannst du ihm noch die Möglichkeit geben, zu einem späteren Zeitpunkt diese Dateien zu sichern - oder ihm die möglichkeit geben, die geöffneten Dateien trotzdem zu sichern.

btw @ViperNeo: Wenn du Probleme mit irgendwas hast, immer deinen Quellcode mitschicken, damit wir sehen können was du bisher versucht hast.

mfG TripleX

12.01.2010 - 22:01 Uhr

ich verwende zwar kein Prism , aber meine ViewModelBase besteht (bisher) aus:

public abstract class ViewModelBase : DispatcherObject, INotifyPropertyChanged, INotifyPropertyChanging, IDisposable

und meine ValidatingViewModelBase besteht aus:

public class ValidatingViewModelBase : ViewModelBase, IDataErrorInfo

deine 2te frage kann ich dir nicht beantowrten, da ich wie gesagt nicht mit Prism arbeite.

MfG TripleX

12.01.2010 - 21:57 Uhr

einfach die Fehlermeldung ignorieren, oder die Beta von Visual Studio 2010 runterladen. Wenn du viel mit WPF arbeitest, würde ich dir das sogar empfehlen. Die Beta macht zwar manchmal nochn paar zicken, aber man kann gut damit arbeiten.

12.01.2010 - 00:44 Uhr

verwendetes Datenbanksystem: SQL Compact 3.5 mit LinQ

Halo Gemeinde,

ich habe folgendes Problem: Ich habe eine SQL Compact 3.5 Datenbank welche mittels Linq2Sql (automatisch) gemapped wurde.

Jetzt wollte ich einer DataGrid Daten aus einer Tabelle anzeigen lassen, damit der Benutzer diese ändern kann. Dazu habe ich mir eben ein DataGrid erstellt und die Items an eine Observable-Collection gebunden. Das Ganze funktioniert soweit und cih kann Daten ändern und diese werden auch in der Datenbank gespeichert.

Jetzt wollte die Funktion einbinden, dass wenn der User auf den Button "Cancel" drückt, die Änderungen nicht in die Datenbank übernommen werden. Nur wenn der User auf "Save" klickt sollen die Daten commitet werden. Aber irgendwie steh ich da aufm Schlauch. Also folgendes habe ich bisher:

View mit DataGrid:

		<DataGrid ItemsSource="{Binding NetworkDrives}"
				  AutoGenerateColumns="False"
				  >
			<DataGrid.Columns>
				<DataGridTextColumn Header="Server-Address"  Binding="{Binding UNC}"/>
				<DataGridTextColumn Header="Standard Drive Letter"  Binding="{Binding StandardDriveLetter}"/>
				<DataGridCheckBoxColumn Header="Mount On Connect"  Binding="{Binding MountOnConnect}" />
			</DataGrid.Columns>
		</DataGrid>

ViewModel mit der Observable Collection und den Commands zum speichern bzw. abbrechen:

#region Private Members
        private ObservableCollection<NetworkDrive> _networkDrives;
        private DbTransaction _transaction;
        private Database _db;
        #endregion

        #region Public Properties
        public ObservableCollection<NetworkDrive> NetworkDrives
        {
            get
            {
                if (_networkDrives == null)
                {
                    _networkDrives = new ObservableCollection<NetworkDrive>();
                    var query = _db.NetworkDrives;
                    foreach (var item in query) _networkDrives.Add(item);
                }
                return _networkDrives;
            }
        }
        #endregion
        //...
        private void ExecuteSaveDataCommand()
        {
            _transaction.Commit();
        }
        //...
        private void ExecuteCancelCommand()
        {
            _transaction.Rollback();
        }
        //...
        public NetworkDrivesSettingsViewModel()
        {
            _db = new Database(@"Data Source=.\database.sdf");
            _db.Connection.Open();
            _transaction = _db.Connection.BeginTransaction();
            _db.Transaction = _transaction;
        }
        #endregion

Nur funktioniert das ganze nicht wie gewünscht, denn er speichert mir gar keine Änderungen ab. Was mache ich falsch?

Btw, noch ne andere Frage - wollte deswegen keinen neuen Thread aufmachen:
Ist es in Ordnung wenn ich DataBase als Singleton implementiere (Das Programm ist nicht multiuser-fähig)?

11.01.2010 - 22:48 Uhr

in Visual Stusio 2010 ist IntelliSense auch deutlich schlauer geworden. gibt man zum Beispiel TextBox ein, findet er auch alle textBoxen, welche zum Beispiel "NameTextBox" heissen 👍

11.01.2010 - 21:28 Uhr

Hallo Gemeinde,

ich wollte mal wissen, wie man (im MVVM-pattern) am besten einen DialogResult setzt. Um das DialogResult direkt gehts mir weniger, sondern darum dass ein dialog geschlossen wird. Beim "Cancel" Button gibts da ja keine Probleme, da sich das Fenster automatisch schließt, aber beim IsDefault Button möchte ich es eben gerne so haben, dass das Fenster geschlossen wird. Bisher habe ich das mit nem Click-Event im Code-Behind geregelt (wo ich dann DialogResult=true gesetzt habe), ist zwar nicht ganz im Sinne von MVVM, aber da dass ja eine GUI-Geschichte ist bin ich recht zufrieden.

Ich wollte aber mal fragen ob es auch ohne Code-Behind Datei geht.

11.01.2010 - 21:16 Uhr

welche Version von Visual Studio verwendest du denn? Denn soweit ich mich erinnern kann hatte ich das Problem beim 08er ebenfalls. Das war mit ein Grund warum ich auf die 10 umgestiegen bin.

11.01.2010 - 18:39 Uhr

du könntest versuchen, mittels dem OutputDataReceived-Event oder dem StandardOuput-Stream die Ausgabe in der Console anzeigen zu lassen.

btw, was sollte:

Console.WriteLine(putty.Start());

bezwecken?

11.01.2010 - 17:35 Uhr

Hallo Gemeinde,

ich habe seit kurzem die Reflection.Emit entdeckt und bin begeistert was man nicht alles in .NET machen kann. Jetzt hätte ich eine Idee, aber bevor ich lange rumprobiere wollte ich euch mal fragen ob es Prinzipiell möglich ist.

Mich nervt es dass ich, wenn eine Property mit INotifyPropertyChanged-Funktion, haben möchte mir extra eine private Variable erstellen muss (kennt sicher jeder). Jetzt Hatte ich die Idee das vielleicht mittels Reflection.Emit die set-Funktion der property überschreiben / ändern könnte, damit eben die Funktion von INotify aufgerufen wird. Dazu würde ich mir eine Klasse schreiben (z.B. PropertyObserver *g) und dort alle Properties einer angegeben Klasse auslese und umändere.

So - wäre so etwas möglich oder kann man generell keine Funktionen "ändern". Ich glaube eher zweiteres, denn es könnte eine potenzielle Gefahr geben wenn man Funktionen abändert. Aber vielleicht geht es ja doch??

MfG TripleX

11.01.2010 - 17:24 Uhr

danke für eure Antworten.

11.01.2010 - 17:19 Uhr

@TripleX
*.dbml ist eine Linq-To-SQL Meta-Datei. Das hat nix mit einem DataSet zu tun. L2S ist ein einfacher O/R-Mapper, der in den meisten Fällen eh einfacher zu verwenden ist als ein DataSet. Das ist nicht deine Datenbank sondern eine Datei welche die Datenbank beschreibt. Die Datenbank ist eine andere Datei die bei SQL Compact normalerweise direkt daneben liegt und auf *.sdf endet.

Danke nochmal für den Hinweis, aber dass wusste ich schon, da ich gerade durch das Thema O/R Mapper auf das ganze Thema hier gekommen bin.

Meine Frage wegen dem DataSet war eher so gedacht: Ich habe in einem Projekt meine "Datenbank" (in dem Fall dann das DataSet welche die Daten einer xml-Datei eingelesen bekommt.) In einem anderen Projekt habe cih dann meine "Models", was in dem Falle die *.dbml Datei wäre. Jetzt wollte ich halt wissen ob man die *.dml irgendwie mit dem DataSet verknüpfen kann. Beim der SQL Compact Datenbank muss ich dafür die Tabellen im *.dbml erstellen und einen ConnectionString angeben. Ersteres würde ich hinkriegen bei einem DataSet, aber dann bin ich am verbinden des DataSets mit dem O/R-Mapper gescheitert.

Denn cih habe gerade ein kleiens Projekt, wo eine SQL-Datenbank eigentlich viel zu "overweight" ist. Außerdem möchte ich den benutzern nicht zumuten, sich extra SQL Compact 3.5 herunterzuladen (oder ich liefere die *.dlls mit, worauf cih auch gerne verzichte würde). Deswegen würde ich Daten am liebsten in eine xml-Datei in Verbindung mit einem DataSet speichern.

MfG TripleX

11.01.2010 - 17:10 Uhr

ich weiß selber nicht mehr, was ich mir bei max gedacht habe. Ich glaube dass ich damit den endwert für die schleife meinte. dadurch merkt man wie wichtig eine saubere Benennung der Variablen ist. Ich habe bei dem beispiel leider auf eine saubere benennung der variablen (+ Funktionen) verzichtet, da ich nur schnell eine Lösung präsentieren wollte. Wird in Zukunft (hoffentlich) nicht mehr passieren.

MfG TripleX

11.01.2010 - 01:01 Uhr

Hallo Gemeinde,

ich habe mir heute überlegt ob es nicht sinnvoll wäre, bei der Implementierung von INotifyPropertyChanged einen "Cache" einzubauen.

Der Vorteil den ich sehe ist der, dass nicht immer ein neues PropertyChangedEventArg erstellt werden muss sobald die Funktion aufgerufen wird.

Nachteil ist dabei aber dass die Klasse etwas "größer" wird (vom Speicherverbrauch) und dass er jetzt bei jeder ChangeNotification erstmal das Dictionary durchsuchen muss:


        private readonly Dictionary<string, PropertyChangedEventArgs> _propertyChangedEventArgsCache = new Dictionary<string, PropertyChangedEventArgs>();
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventArgs args;
            if (!_propertyChangedEventArgsCache.TryGetValue(propertyName, out args))
            {
                args = new PropertyChangedEventArgs(propertyName);
                _propertyChangedEventArgsCache.Add(propertyName, args);
            }

            NotifyPropertyChanged(args);
        }
        public void NotifyPropertyChanged(PropertyChangedEventArgs args)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, args);
            }
        }

Was meint ihr was besser ist - ohne cache oder mit?

€dit: naja nach nem simplen Test hab ich gemerkt dass es ohne Cache viel schneller ist. War wohl ne dumme Idee 😃

MfG TripleX

10.01.2010 - 23:00 Uhr

Was mir noch auffält: Wenn du das Minimum berechnet, solltest du es auch Minimum nennen und nicht Maximum 😄

Kein kommentar 👅

Math.Min(a.Count, b.Count)

danke hab dass auch direkt mal getestet welches (nach 100010001000 Aufrufe) von den beiden schneller. Es tritt an:

int min = 123 < 60 ? 123 : 60;
//vs.
int min = Math.Min(123, 60);
:question: : 3941
Math.Min: 5338

Auf die 1,4 Sekunden kommt's dann auch nicht wirklich an, und die Math.Min()-variante ist eindeutig besser zu verstehen

10.01.2010 - 22:27 Uhr

das mit der CompareTo ist eine super idee 😃[/csharp]
aber deinen Einwand mit a_ != b_ kann ich nicht verstehen. Habe es mal getestet und CompareByNumber("1.1","1.0") liefert mir eine 1 zurück (was auch richtig ist)

hab es mal mit linq getestet und es funktioniert ebenso:

        private static int CompareByNumber(String x, String y)
        {
            if (x == y) return 0;

            var a = x.Split('.').Select((z) => Convert.ToInt32(z));
            var b = y.Split('.').Select((z) => Convert.ToInt32(z));

            int max = a.Count() < b.Count() ? a.Count() : b.Count();
            for (int i = 0; i < max; i++)
            {
                if (a.ElementAt(i).CompareTo(b.ElementAt(i)) != 0)
                    return a.ElementAt(i).CompareTo(b.ElementAt(i));
            }
            return a.Count() - b.Count();
        }

Btw, wollte mal schauen welche Methode schneller ist:

Stopwatch watch = new Stopwatch();
            watch.Start();
            for (int i = 0; i < 1000; i++)
            {
                for (int j = 0; j < 1000; j++)
                {
                    List<string> strings = new List<string>() {
                        { "1.1" }, { "1.0"}, {"1.123456"},
                        { "1.1.2" }, { "1.7" }, { "1.2.1.2"},
                    };
                    strings.Sort(CompareByLinq);
                }
            }
            watch.Stop();
            Console.WriteLine("CompareByLinq: " + watch.ElapsedMilliseconds);
            watch.Reset();

            watch.Start();
            for (int i = 0; i < 1000; i++)
            {
                for (int j = 0; j < 1000; j++)
                {
                    List<string> strings = new List<string>() {
                        { "1.1" }, { "1.0"}, {"1.123456"},
                        { "1.1.2" }, { "1.7" }, { "1.2.1.2"},
                    };
                    strings.Sort(CompareByNumber);
                }
            }
            Console.WriteLine("CompareByNumber: " + watch.ElapsedMilliseconds);
            watch.Reset();

Hier die Ausgabe der Konsole (Zeiten in ms)

CompareByLinq: 104122
CompareByNumber: 15268
10.01.2010 - 22:08 Uhr

wow danke, ich hätte schon viel eher fragen sollen. Wirklich genial das Programm. (ein paar Sachen werde ich zwar noch ändern aber an sich bin ich sehr zufrieden)

10.01.2010 - 21:45 Uhr

Also ich habe jetzt mal die "local database" (SQL Compact 3.5) genommen und bin damit Recht zufriden. Was ich genial daran finde ist, dass man sich mittels dem Programm sqlmetal eine *.dbml - Datei generieren kann. Ist wirklich eine sehr schöne Sache. 👍

Weiß zufällig jemand ob man diese *.dbml auch mit einem dataset (welches die Daten aus einer xml-Datei bekommt) verwenden kann. Habe mich gestern daran versucht aber habs nicht hingekriegt 🤔

Ich habe noch nie "Add Item" geklickt, ich schreibe immer den Code direkt ohne Assistent. Siehe Link in meiner Signatur.

hast du da wirklich noch nie darauf geklickt 8o?

10.01.2010 - 21:38 Uhr

PS: Mit LINQ kann man da noch einiges kürzer zaubern, aber implementiers doch erstmal so

Könntest du mal zeigen wie, oder zumindest die Vorgehensweise erläutern?

10.01.2010 - 21:28 Uhr

Hallo Gemeinde,

da ich Ordnung liebe (zumindest in Quellcode *g) wollte ich mal fragen ob es eine möglichkeit gibt (z.B. über Addins oder ähnliches) meinen Code folgendermaßen zu sortieren:

    public class NetworkDriveViewModel : ViewModelBase
    {
        #region Private Members
        //...
        #endregion

        #region Public Properties
        //...
        #endregion

        #region Public Commands
        //...
        #endregion

        #region Public Actions
        //...
        #endregion

        #region Public Events
        //...
        #endregion

        #region Constructors
        //...
        #endregion

        #region Private Methods
        //...
        #endregion

        #region EventHandling
        //...
        #endregion

        #region IDisposable Implemetation
        //...
        #endregion
    }

Am besten wäre es halt dass ich nur ein Button drücke, dann wird eine Funktion aufgerufen der meinen Code analysiert und die #regions (je nach Bedarf) einfügt

Denn ich verbrauche viel zeit dafür, in meinen ganzen Klassen den Code so "sauber" zu halten. Da kann es eig. nicht schaden etwas Zeit zu investieren in eine Funktion, die dass automatisch macht. Ich könnte natürlich auch ein eigenes Programm dazu schreiben, aber ich bräuchte halt aufjedenfall einen Shortcut oder Button im Visual Studio.

MfG TripleX

10.01.2010 - 21:12 Uhr

hallo Gemeinde, ich habe mir demletzt einige Codesnippets gebastelt, und wollte diese euch natürlich nicht vorenthalten (habe im Forum nach einem Sammelthread oder ähnliches gesucht, bin aber nicht fündig geworden).

Singelton-Pattern (singleton)
Implementiert (fast) das Singleton-pattern. Der private Konstruktor muss noch erstellt werden.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet" >
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>Singleton Snippet</Title>
      <Shortcut>singleton</Shortcut>
      <Description>Code snippet for implementing the Singleton Pattern (Threadsafe)</Description>
      <Author>David Teck</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal Editable="false">
          <ID>TypeObject</ID>
          <Function>SimpleTypeName(System.Object)</Function>
        </Literal>
        <Literal>
          <ID>classname</ID>
          <ToolTip>Class name</ToolTip>
          <Function>ClassName()</Function>
          <Default>ClassNamePlaceHolder</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
<![CDATA[$end$#region Singleton
        private static volatile $classname$ _instance;
        private static object _lock = new $TypeObject$();
        /// <summary>
        /// Get the unique instance of <see cref="$classname$"/>.
        /// This property is thread-safe.
        /// </summary>
        public static $classname$ Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null) _instance = new $classname$();
                    }
                }
                return _instance;
            }
        }
        #endregion]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

NotifyProperty (notprop)
Erstellt eine Property, welche Änderungen - über meine Implementierung von INotifyPropertyChanged (siehe weiter unten) - bekannt gibt.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet" >
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>NotifyProperty Snippet</Title>
      <Shortcut>notprop</Shortcut>
      <Description>Code snippet for a Property which notifies updates with INotifyPropertyChanged</Description>
      <Author>David Teck</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>type</ID>
          <ToolTip>The type of the property</ToolTip>
          <Default>bool</Default>
        </Literal>
        <Literal>
          <ID>fieldname</ID>
          <ToolTip>The name of the property</ToolTip>
          <Default>name</Default>
        </Literal>
        <Literal>
          <ID>propname</ID>
          <ToolTip>The name of the property</ToolTip>
          <Default>Name</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
<![CDATA[private $type$ $fieldname$;
        public $type$ $propname$
        {
            get { return $fieldname$; }
            set
            {
                if (value != $fieldname$)
                {
                    $fieldname$ = value;
                    NotifyPropertyChanged("$propname$");
                }
            }
        }$end$]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

INotifyPropertyChang(ed/ing) Implementierung (inotitfy):
Implementiert das INotifyPropertyChanged-Interface oder das INotifyPropertyChanging-Interface

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet" >
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>INotifyPropertyChang(ed/ing) Snippet</Title>
      <Shortcut>inotify</Shortcut>
      <Description>Code snippet for implementing INotifyPropertyChang(ed/ing)</Description>
      <Author>David Teck</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>event</ID>
          <ToolTip>This specifies the type of the event</ToolTip>
          <Default>ed</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
<![CDATA[$end$#region INotifyPropertyChang$event$ Implementation
        /// <summary>
        /// Declares the <see cref="PropertyChang$event$"> event
        /// </summary>
        public event PropertyChang$event$EventHandler PropertyChang$event$;
        /// <summary>
        /// This method will raise the <see cref="PropertyChang$event$"> event passing the
        /// source property that is being updated.
        /// </summary>
        /// <param name="propertyName">Name of the chang$event$ property.</param>
        public void NotifyPropertyChang$event$(String propertyName)
        {
            NotifyPropertyChang$event$(new PropertyChang$event$EventArgs(propertyName));
        }
        /// <summary>
        /// This method will raise the <see cref="PropertyChang$event$"> event passing the
        /// source properties that are being updated.
        /// </summary>
        /// <param name="propertyNames">Name of the chang$event$ properties.</param>
        public void NotifyPropertyChang$event$(String[] propertyNames)
        {
            foreach(string prop in propertyNames)
                NotifyPropertyChang$event$(new PropertyChang$event$EventArgs(prop));
        }
        /// <summary>
        /// This method will raise the <see cref="PropertyChang$event$"> event passing the
        /// source property that is being updated.
        /// </summary>
        /// <param name="args"><see cref="PropertyChang$event$EventArgs"/> of the chang$event$ property.</param>
        public void NotifyPropertyChang$event$(PropertyChang$event$EventArgs args)
        {
            if (PropertyChang$event$ != null)
            {
                PropertyChang$event$(this, args);
            }
        }
        #endregion]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

IDisposable Implementierung (idisposable):
Implementiert das IDisposable-Interface

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet" >
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>IDisposeable Snippet</Title>
      <Shortcut>idisposable</Shortcut>
      <Description>Code snippet for implementing IDisposeable</Description>
      <Author>David Teck</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>classname</ID>
          <ToolTip>Class name</ToolTip>
          <Function>ClassName()</Function>
          <Default>ClassNamePlaceHolder</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
<![CDATA[$end$#region IDisposable Implemetation
        ~$classname$ ()
        {
           Dispose (false);
        }
        /// <summary>
        /// Disposes the <see cref="$classname$"/>
        /// </summary>
        public void Close ()
        {
           ((IDisposable)this).Dispose ();
        }
        /// <summary>
        /// Closes and disposes the <see cref="$classname$"/>
        /// </summary>
        void IDisposable.Dispose ()
        {
           Dispose (true);
           GC.SuppressFinalize (this);
        }
        /// <summary>
        /// This method is called by <see cref="Dispose()"/>. 
        /// Derived classes can override this method.
        /// </summary>
        /// <param name="cleanManagedResources">
        /// <para><see langword="true"/>: Disposes managed and unmanaged resources</para>
        /// <para><see langword="false"/>: Disposes only unmanaged resources</para>
        /// </param>
        protected virtual void Dispose(bool cleanManagedResources)
        {
            if (cleanManagedResources)
            {
                // Clean up the managed resources
            }
            // Clean up the unmanaged resources
        }
        #endregion]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

Event (event)
Erstellt ein simples event

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet" >
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>Event Snippet</Title>
      <Shortcut>event</Shortcut>
      <Description>Code snippet for creating an event</Description>
      <Author>David Teck</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>name</ID>
          <ToolTip>Specify the name of the event</ToolTip>
          <Default>MyEvent</Default>
        </Literal>
        <Literal>
          <ID>comment</ID>
          <ToolTip>Specify the XML-Comment for the event</ToolTip>
          <Default></Default>
        </Literal>
        <Literal>
          <ID>access</ID>
          <ToolTip>Specify the accessibility the event</ToolTip>
          <Default>public</Default>
        </Literal>
        <Literal>
          <ID>handler</ID>
          <ToolTip>Specify the EventHandler for the event</ToolTip>
          <Default>EventHandler</Default>
        </Literal>
        <Literal>
          <ID>param</ID>
          <ToolTip>Specifies the parameter for the event</ToolTip>
          <Default>EventArgs.Empty</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
<![CDATA[$end$#region $name$-Event
        /// <summary>
        /// Occurs when $comment$
        /// </summary>
        $access$ event $handler$ $name$;
        private void On$name$()
        {
            if ($name$ != null) $name$(this, $param$);
        }
        #endregion]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

SimpleCommand (mvvm_simcom)
_Erstellt einen neuen SimpleCommand (Command für WPF) _

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet" >
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>MVVMFrameWork - SimpleCommand Snippet</Title>
      <Shortcut>mvvm_simcom</Shortcut>
      <Description>Code snippet for a SimpleCommands</Description>
      <Author>David Teck</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Imports>
        <Import>
          <Namespace>MVVMFrameWork.Commands</Namespace>
        </Import>
      </Imports>
      <Declarations>
        <Literal>
          <ID>fieldname</ID>
          <ToolTip>The name of the command</ToolTip>
          <Default>name</Default>
        </Literal>
        <Literal>
          <ID>propname</ID>
          <ToolTip>The name of the command</ToolTip>
          <Default>Name</Default>
        </Literal>
        <Literal>
          <ID>cancode</ID>
          <ToolTip>The code which indicates if the command can be executed</ToolTip>
          <Default>true</Default>
        </Literal>
        <Literal>
          <ID>docode</ID>
          <ToolTip>The code which will be executed</ToolTip>
          <Default></Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
<![CDATA[$end$#region $propname$Command
        private SimpleCommand $fieldname$Command;
        public SimpleCommand $propname$Command
        {
            get {
                if ($fieldname$Command == null)
                    $fieldname$Command = new SimpleCommand(x => Execute$propname$Command(), x => CanExecute$propname$Command);
                return $fieldname$Command;
            }
        }
        /// <summary>
        /// Called, when the <see cref="$propname$Command"/> should be executed.
        /// </summary>
        private void Execute$propname$Command()
        {
            $docode$
        }
        /// <summary>
        /// <see langword="true"/> if the <see cref="$propname$Command"/> can be executed.
        /// </summary>
        private bool CanExecute$propname$Command
        {
            get
            {
                return $cancode$;
            }
        }
        #endregion]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

Falls ihr Verbesserungsvorschläge oder andere Snippets habt, welche ihr austauschen möchtet, dann postet sie doch bitte hier 😃

Schlagwörter: Singleton, INotifyPropertyChanged, IDisposable, SimpleCommnd, Snippet

10.01.2010 - 20:36 Uhr

        private static int CompareByNumber(String x, String y)
        {
            if (x == y) return 0;

            string[] a = x.Split('.');
            string[] b = y.Split('.');

            int max = a.Length < b.Length ? a.Length : b.Length;
            for (int i = 0; i < max; i++)
            {
                if( a[i] != b[i] ) return (Convert.ToInt64(a[i]) - Convert.ToInt64(b[i])) > 0 ? 1 : -1;
            }
            return a.Length - b.Length;
        }

            List<string> strings = new List<string>() {
                { "1.1" }, { "2.2.3.4"}, {"1.123456"},
                { "1.1.2" }, { "1.7" }, { "1.2.1.2"},
            };
            strings.Sort(CompareByNumber);

Keine Garantie auf Richtigkeit, aber die liste sieht nach'm sortieren gut aus. Anstatt Convert.ToInt64() kann man natürlich auch Convert.ToInt32 (oder die TryParse Methode, welche oben bereits angesprochen wurde), verwenden.

10.01.2010 - 17:59 Uhr

ja natürlich macht das Sinn, nur ich habe daran nicht gedacht - und ich war halt froh dass ich es (nach ner langen nacht) hingekriegt habe. Jetzt werden es wohl ein paar Nächte mehr werden dass ich dran arbeite.

10.01.2010 - 17:57 Uhr

sieht sehr gut aus (für ein Schulprojekt!)

Screeenshot: siehe anhang

10.01.2010 - 16:33 Uhr

danke für deinen Beitrag, hat mir weitergeholfen! Werde nachher mal schauen wie das ist, wenn ich 2 Events abfangen möchte, hab das nämlich noch gar nicht probiert hehe

€dit: ja das geht nicht ... 'Property is set more than once' ... und ich hab mich schon gefreut dass es funktioniert 👅

10.01.2010 - 15:17 Uhr

@Mr. Evil:

so schlau ist meine Implementierung noch nicht, ich kann bisher nur folgendes machen:


        MVVM:EventBinding.Event="Loaded"
        MVVM:EventBinding.Action="{Binding LoadedAction}"
        MVVM:EventBinding.Command="{Binding LoadedCommand}"
        MVVM:EventBinding.CommandParameter="{Binding CommandParameter}"

Aber so reicht mir das erstmal. Sobald ich mehr brauche, wird es eben implementiert 😃

die loesung mit dem link zuvor ist problematissch wenn man mehrere events binden moechte aber die controls keine child elemente im visual tree erlauben - dann geht das nicht

kannst du dazu mal ein kurzes beispiel posten? verstehe nämlich nicht ganz was du meinst.

10.01.2010 - 15:05 Uhr

Dafür musst du dir (leider) selber eine Klasse zusammenbasteln oder eine bereits fertige Implementierung verwenden (Stichpunkt EventBinding oder AttachedCommands).

Dass ganze ist aber, wenn du es selber baust nicht ganz einfach., da man mit Reflection arbeiten muss. Die Klassen vom oben angegeben Link habe ich bs vor wenigen Minuten selber noch verwendet, bin aber gerade fertig mit meiner eigener Implementierung geworden.

Wenn du Fragen hast, einfach fragen 😃

MfG TripleX

10.01.2010 - 04:31 Uhr

Problem behoben ... ich hatte (weil ich es früher gebraucht habe) als Datentyp von StatusImage ImageSource, habe es jetzt in string geändert und jetzt geht's 😃

09.01.2010 - 23:27 Uhr

verwendetes Datenbanksystem: weiss i no net 👅

Hallo Gemeinde,

ich habe mal eine Frage wie man (lokale) Daten in einer Datebank am besten speichert.
Bisher habe ich immer ein dataset verwendet, welches ich als xml-datei gespeichert habe. Aber da gibts doch bestimmt bessere Alternativen. Also wenn ich in meinem Projekt auf "Add / New Item" klicke, bekomme ich ja ein paar Sachen angezeigt (siehe Daeianhang).

Was mir ins Auge springt ist die "local database". Doch wenn ich das Projekt weitergebe an jemand anders, der nur .NET Framework installiert hat (und kein SQL-Server oder ähnliches), funktioniert dass dann trotzdem? Gibts sonst noch alternativen?
Außerdem werde ich, wenn ich des auswähle, nach einem Typ gefragt (zur Auswahl stehen DataSet und Entinity Data Model) 🤔

MfG TripleX

09.01.2010 - 23:18 Uhr

Also wenn der Pfad zur Datei sicher stimmt (am besten davor immer mit Files.Exist() prüfen) dann könnte es meiner Meinung nach nur noch am leerzeichen liegen 🤔. Probier mal die Datei umzubenennen in "Intel_Chipset.exe"

09.01.2010 - 22:36 Uhr

Ich habe in Erinnerung das "Environment.CurrentDirectory" keine gute Wahl ist. Verwende lieber "AppDomain.CurrentDomain.BaseDirectory"

Lies dir am besten mal den Thread durch (auch den hinweis ganz unten!)
[FAQ] Pfad zur eigenen Anwendung (EXE) ermitteln

09.01.2010 - 22:18 Uhr

Das geht mittels .:
Dieser Operator trifft auf jedes einzelne druckbare oder nicht druckbare Zeichen zu, außer unter Umständen auf ein Newline-Zeichen (Neue Zeile) oder auf Null-Zeichen, also leere Strings. Das Punktzeichen (.) repräsentiert diesen Operator