Laden...
T
teebeast myCSharp.de - Member
Softwareentwickler Bayern Dabei seit 29.12.2010 50 Beiträge
Benutzerbeschreibung

Forenbeiträge von teebeast Ingesamt 50 Beiträge

04.08.2023 - 08:49 Uhr

Hallo,

folgendes Zitat hat mich dazu animiert, hier mal eine architektonische Frage zum MVVM-Pattern zu stellen, da ich in meinem Team eine bisher noch nicht geklärte Diskussion zum Grad der Abstraktion führe.

Zitat von Abt

Die Austauschbarkeit von UI-Pattern erreichst Du mit einer Drei-Schichten-Architektur.

Das Model kannst Du i.d.R. wiederverwenden, aber nicht das ViewModel.
Das ViewModel ist vereinfacht ausgedrückt die UI-Logik für die View - und die sind sehr eng miteinander gekoppelt. Sowohl die Implementierung wie auch die Technik.

View und ViewModel haben zudem i.d.R. eine Abhängigkeit zu einem konkreten UI-Framework.
Die View kannst Du also problemlos innerhalb von WPF tauschen. Du kannst aber i.d.R. eben nicht das ViewModel zwischen Frameworks sharen.
Das ist auch nicht die Idee dahinter.

Wenn wir Oberflächen entwickeln, habe wir in der Regel eine Assembly, dieMyProject.UIheißt. Hier wird alles implementiert, was zum MVVM-Pattern gehört. Die meisten Klassen sindinternalgekennzeichnet und Aufrufe von Fenstern werden über Hilfsmethoden angeboten, wo das Verbinden von UI und ViewModel geschieht. Das Laden der Daten geschieht per IoC angeforderten Provider-Klassen, welche die Daten für die Bindung dem ViewModel zur Verfügung stellen oder Präsentationsobjekten.

Ich persönlich weigere mich für ViewModels als auch Präsentationsobjekten eine pauschale Abstraktion durch Interfaces einzuführen, vor allem da all diese Klassen internal sind. Ich habe für mich noch kein Szenario gehabt, in dem mir diese pauschale Abstraktion geholfen hätte. In manchen Fällen habe ich konkrete Gründe, eine Schnittstelle für spezielle Aufgaben einzuführen, aber auch diese sind in der Regel auch nur innerhalb der Assembly sichtbar.

Das meist angeführte Thema ist die Testbarkeit dieser Klassen. Aber selbst hier sehe ich keinen Grund von meiner Vorgehensweise abzuweichen. PO-Objekte tragen nur Informationen und jegliche Test-Implementierung dieser Klassen würde wieder genauso aussehen. ViewModels sind schon etwas kritischer, aber hier kann die Entkoppelung für den Test über den IoC-Container gelöst werden. Müssen also auch nicht gesondert für den Test implementiert werden. Ansonsten folge ich dem Gedanken von Abt, dass die Wiederverwendbarkeit all dieser Klassen nur sehr bedingt möglich ist, sodass sich der Overhead der Abstraktion meiner Meinung nach in keiner Weise lohnt.

Ich folge hier inzwischen einen sehr pragmatischen Ansatz, der für das Umfeld bei meinem Arbeitgeber gut funktioniert. Ich habe gemerkt, dass gewisse Komplexitäten von allen Entwicklern verstanden und umgesetzt werden müssen. Es hat sich gezeigt, dass gewisse architektionische Ansätze ad absurdum geführt werden, wenn diese nicht von allen verstanden und auch umgesetzt werden. Uns fehlen hier auch gewisse Konstrollstrukturen wie Softwarearchitekten oder Code Reviews. Auch der Wissenstransfer zur korrekten Anwendung unserer eigenen Frameworks und Strukturen ist noch ausbaufähig. Somit empfinde ich die Abstraktion eher als Over-Engineering.

Konkret haben wir in einem Projekt diese abstrakte Variante umgesetzt. Der UI-Bereich besteht nun aus mindestens vier Assemblies wobei eine davon sich um die Abstraktion der Modelle und eine andere um die Abstraktion der ViewModels und der DataProvider kümmert. Architektionisch ist das alles aus theoretischer Sicht sehr schön gelöst. Nur hat sich der Implementierungsaufwand und somit auch die Zeit erhöht. An der Umsetzung des Projektes selbst war ich nicht beteiligt, merke aber dass ich erhebliche Probleme habe, mich im Quellcode zu orientieren. Am Projekt beteiligte Entwickler verstehen den Grund der Komplexität nicht und sind davon eher genervt. Das Entwickeln geht in dem Projekt nicht mehr so flüssig von der Hand.

Ich hoffe, ich konnte meine Gedanken einigermaßen gut niederschreiben. Mich interessiert, wie Ihr das Thema seht bzw. auch angeht. Darf auch gerne allgemein gehalten sein, da es nicht unbedingt ein MVVM spezifisches Thema ist.

Grüße

04.08.2023 - 07:18 Uhr

Du scheinst grundsätzlich Verständnisprobleme bei logischen Operatoren sowie mit LINQ zu haben. Ich kann Dir nur empfehlen, Dich damit ein wenig auseinander zu setzen. Der Lösungsansatz von MrSparkle ist bereits vollständig korrekt.

query = query.Where(entity => entity.MachineId == machineId)

Dieser Ausdruck reduziert bereits Deine Ergebnismenge. Die Kombination von weiteren Where-Ausdrücken kann als Und-Verknüpfung interpretiert werden. Somit ist folgender Code völlig unnötig, da über die beiden vorherigen if-Bedingungen die Ergebnismenge bereits auf diese Bedingungen reduziert wurde.

if ((lindeId > 0) && (machineId > 0))
{
 query = query.Where(entity => entity.LineID == lineID &&  entity.MachineId == machineId)
}

Am besten mal austesten, um zu verstehen, was hier passiert. Das hilft ungemein.

Dieser Lösungsansatz hilft nur, wenn alle Deine Filter-Parameter die Ergebnismenge immer reduzieren sollen. Bei Entweder-Oder-Filterungen braucht man eine etwas angepasste Strategie. Aber so wie ich das lese, sollte das bei Dir wohl eher nicht der Fall sein.

Grüße

08.05.2023 - 08:25 Uhr

An sich lässt sich das ganz einfach für Strings lösen. Man baut sich eine Liste mit den Strings auf und filtert die nicht benötigten Elemente mit der Where-Methode aus System.Linq aus. Die verbleibenden Elemente können dann verarbeitet werden.

var a = "Wert 1";
var b = "Wert 2";
var list = new List<string> { a, b }; 
var filtered = list.Where(x => x != "Wert 1");	// ggf. mit string.Equals arbeiten, wenn Groß-/Kleinschreibung ignoriert werden soll

foreach (var value in filtered)
{
    // Verarbeiten
}

Wenn komplexere Strukturen entstehen, macht es Sinn, diese in Klassen bzw. in Interfaces auszulagern. Hierbei werden dann die Klassen/Interfaces in der Liste gehalten und können über die Eigenschaften gefiltert werden. Funktioniert also analog.

04.04.2023 - 08:08 Uhr

Hi,

ich habe nicht im Detail nachgeschaut, aber könnte es nicht sein, dass eine Where-Bedingung in einem Include nicht zulässig ist?

Mein Lösungsansatz wäre hier ein Mapping TeamPlans in Project zu erstellen, dass den ForeignKey ProjectId und TeamId berücksichtigt. Dann bräuchte man keine Where-Bedingung im Include.

Grüße

20.08.2022 - 09:08 Uhr

Wie soll denn die Methode PostCard aufgerufen werden? Soll das durch eine manuelle Aktion gestartet werden oder irgendwie automatisch passieren?

Die Frage ist, ob hier ein Event überhaupt notwendig ist. Dein UserControl könnte eine Methode habe, wo der darzustellende Text von außen übergeben werden kann. Sehr wahrscheinlich wird Dein Fenster die Kontrolle über Deine Klasse ApiRequest haben, da dort die Instanz erzeugt wird und somit auch Kontrolle über die die Methode PostCard. Passe die Methode an, sodass sie Deinen erstellter String als Rückgabewert liefert. Wenn Du Dir dann noch die im Fenster dargestellten UserControls merkst, kannst Du den Rückgabewert der Methode des Controls übergeben.

Ach ja, schau Dir mal das Konzept von async und await an. Verwende await statt .Result. Async-Methoden sollten darüber hinaus immer einen Task als Rückgabewert liefern - bis auf Events.

Vermeide MessageBox-Aufrufe in der Logik. Die Aufrufe sollten immer nah an der Oberfläche sein bzw. da wo eine Aktion gestartet wird, also z.B. in einem abonnierten Event. Wird so eine Methode von einem Dienst verwendet, hast Du ein Problem.

17.08.2022 - 12:24 Uhr

Ich habe das Gefühl, dass hier die Logik vertauscht ist. Darüber hinaus ist ein switch-Block ist für ein bool meist ungeeignet, nutze hier einen if-Block.


switch (Filter.HasFlag(_typeOfMessage) == false)
{
    case true:
        Filter |= _typeOfMessage; break;
    default:
        Filter &= ~_typeOfMessage; break;
}

Sollte wohl eher so aussehen:


if (Filter.HasFlag(_typeOfMessage))
{
    Filter &= ~_typeOfMessage; // entfernen, wenn bereits vorhanden
}
else
{
    Filter |= _typeOfMessage;  // hinzufügen, wenn noch nicht vorhanden
}

02.07.2022 - 09:29 Uhr

Hi,

mein Ansatz wäre, dass für ein Objekt (Person, Tier, Auto) an einem Ort (Zimmer, Straße, Kneipe) mit einer gewissen Wahrscheinlichkeit ein Ereignis eintreten kann. Das kann ein Ereignis sein, auf das man keinen Einfluss hat oder eine Reaktion zulässt. Also eine Handlung zulässt. Verhältnisse zwischen Objekten würde ich über Beziehungen abbilden, die definieren wie der aktuelle Stand der Beziehung (z.B. Angestelltenverhältnis) ist.

Ich würde es für den Anfang auch sehr einfach halten. Kümmere Dich erst einmal darum, wie Deine Ereignisse ausgelöst werden und welche Komplexitäten Du hier benötigst. Tritt Dein Ereignis immer nur an einem Ort auf? Kann es auch an mehrere Orten auftreten? Lege ich im Zweifel neue Ereignis-Duplikate an oder versuche ich diese für andere Orte wieder zu verwenden? Die Frage ist in diese Fall, lässt Du Redundanz zu oder reduzierst Du diese durch komplexere Objektstrukturen.

Wichtig ist auch, was siehst Du am Anfang als gegeben an. Hat Dein Charakter immer einen Job? Wenn nein, dann kann er seinem Chef nicht begegnen. Hat Dein Charakter immer ein Haustier? Das kann Auswirkung darüber haben, welche Ereignisse zulässig sind. Heißt Du brauchst ggf. Eigenschaften am Ereignis, dass ein Chef benötigt wird. Kann heißen, dass das Ereignis gar nicht ausgewählt werden darf oder eben nichts passiert, wenn das Ereignis aufgrund der Bedingungen für das Eintreten nicht eintreten kann.

Ich hoffe, ich habe es einigermaßen verständlich geschrieben. Auf die Datenhaltung bin ich nicht eingegangen, da die sich in der Regel aus den gewählten Strukturen von ganz allein ergeben. Es sei nur angemerkt, dass das Pflegen der Daten sehr schnell und einfach gehen sollte und die Daten sich ggf. unabhängig von der eigentlichen Programminstallation aktualisieren lassen sollten.

Ach ja, ich fänd es witzig, wenn man "ruhig bleiben" auswählt, aber der Charakter sich mit einer gewissen Wahrscheinlichkeit trotzdem für "eskalieren" entscheidet, weil zu einem bestimmten Prozentsatz immer "eskalieren" ausgewählt wurde.

29.05.2022 - 17:55 Uhr

Meine Erfahrung mit solchen großen Datenmengen ist, dass es Sinn macht, die Dinger in Ordnern (durchaus mehrere Ebenen) zu organisieren, sodass die Anzahl der Dateien maximal bei einigen Tausend liegt. Ich weiß nicht, ob es eine Auswirkung hat, wenn man große Dateimengen in .NET abfragt. Aber spätestens, wenn man sich die Dinger im Windows Explorer anzeigen lassen will, dann darf man warten.

25.04.2022 - 08:14 Uhr

Wir schreiben die Daten in das lokale Profil des Benutzers, genauer gesagt in die Registry. Datenbank ist hier - denke ich - nicht notwendig, da es sich um unwichtige Informationen handeln, die der Nutzer jederzeit durch die Positionierung des Fensters wieder herstellen kann.

Interessanter ist aber, dass wir die Positionierung abhängig von der Gesamtauflösung (WorkingArea) speichern. Warum? Durch die ganze Homeoffice-Geschichte kommt es häufiger vor, dass auf den Rechner lokal oder remote zugegriffen wird und hier unterschiedliche Monitor-Konstellationen vorhanden sind.

19.04.2021 - 08:35 Uhr

Hi,

wir haben in unseren Projekten immer mal wieder das Problem, dass wir nicht auf Eigenschaften des DataContextes in DataTemplates zugreifen können. Wir nutzen hier eine Hilfsklasse, um das umsetzen zu können. Haben wir irgendwann mal entdeckt und ist recht hilfreich.


/// <summary> Bindet den DataContext gegen Elemente, die nicht im Visual-Tree auftauchen </summary>
public sealed class DataContextBinder : Freezable
{
    /// <summary> Dependency-Property von <see cref="DataContext"/> </summary>
    public static readonly DependencyProperty DataContextProperty =
        DependencyProperty.Register(nameof(DataContext),
            typeof(object),
            typeof(DataContextBinder),
            new PropertyMetadata(null));

    /// <summary> zu bindende DataContext </summary>
    public object DataContext
    {
        get { return GetValue(DataContextProperty); }
        set { SetValue(DataContextProperty, value); }
    }

    /// <summary> Erzeugt eine neue Instanz von <see cref="DataContextBinder"/> </summary>
    protected override Freezable CreateInstanceCore()
        => new DataContextBinder();
}

Definition in der XAML-Datei:


<Window.Resources>
    <utils:DataContextBinder x:Key="DataContextBinder" DataContext="{Binding}"/>
</Window.Resources>

Verwendung:


<DataTemplate>
    <TextBox Text="{Binding Source={StaticResource DataContextBinder}, Path=DataContext.TextProperty}"  />
</DataTemplate>

Vielleicht ist es ja mal nützlich.

26.03.2021 - 07:37 Uhr

Seit einem der letzten Updates gibt es Probleme mit der Windows-Fotoanzeige. Vor allem bei der Darstellung von TIFF-Dateien. Vielleicht betrifft Dich das in Deinem Fall auch.

05.01.2021 - 08:14 Uhr

Ich habe gesehen, dass Du als Abhängigkeit das NuGet StringFormatter verwendest. Überlege mal diese Implementierung durch den Standard zu ersetzen. In .NET Core 5 - und auch schon davor - wurde sehr viel an der Performance und dem Speicherbedarf im Framework optimiert. Ich wäre der Meinung, dass es einen Blog-Eintrag vom Microsoft hierzu gäbe, hab ich nur nicht gefunden. Nur den hier: Performance Improvements in .NET Core 5

24.10.2020 - 11:45 Uhr

So wie es ausschaut, hast Du ja das Objekt language aus der Datenbank (DataContext) geladen. Was im Mapper passiert, ist nicht transparent. Aber Du solltest Deinem translation-Objekt language und nicht mappedLanguage zuweisen. Die werden die identische Id haben und daher kommt die Meldung.

Normalerweise reicht es, die Id einer Referenz zuzuweisen und zu speichern, sofern der DataContext nur für den Zeitraum des Speicherns lebt. Wenn Du den DataContext länger leben lässt - wegen Caching oder ähnlichem - dann kommt man ggf. nicht drum herum auch die Referenz zu setzen. Ich persönlich vermeide es auf DataContext-Ebene zu cachen oder unnötig langlebig zu halten.

Auch verstehe ich nicht, warum die Language gemappt wird. Normalerweise sollte sich doch an dem Objekt in dem Kontext nichts ändern dürfen, oder doch? Die Frage wäre, ob dann die Language nicht ihre eigene Speichermethode bekommt.

10.07.2020 - 09:36 Uhr

Hallo,

Du musst DocumentPage mit der PageSize initialisieren, dann sollte es funktionieren. Anbei Teile meiner Implementierung.

private DocumentPage CreatePage(Grid grid)
{
    var box = this.SizingPageGrid(grid);

    return new DocumentPage(grid, this.PageSize, box, box);
}

private Rect SizingPageGrid(Grid grid)
{
    var box = new Rect(new Point(0, 0), this.PageSize);

    grid.InvalidateArrange();
    grid.UpdateLayout();
    grid.Measure(this.PageSize);
    grid.Arrange(box);

    return box;
}
06.05.2020 - 07:59 Uhr

Ich hatte bisher noch nie wirklich Probleme bei der Umstellung der Visual Studio Version. Meiner Meinung nach riecht es schon sehr stark nach Problemen mit Referenzen.

Wenn das Projekt referenziert ist, prüfe mal, ob im ConfigurationManager alle Projekte zum Bauen aktiv sind. Bei uns ist so ein Fehler häufig aufgrund der falschen Targetplattform (AnyCPU, x86) zurück zu führen.

21.05.2019 - 08:24 Uhr

Ich glaube ich habe mich mit dem Hosting-Angebot etwas unglücklich ausgedrückt. Es würde sich dann in dem Fall nicht mehr um einen Server handeln, sondern nur um ein Webhosting-Paket. Aber es würde überraschenderweise .NET-Core mit anbieten.

https://www.ionos.de/hosting/webhosting

Ob es dann letztendlich meinen Anforderungen entsprechen würde, bleibt noch zu prüfen. Irgend eine Kröte muss man bei solchen Angeboten immer schlucken.

Du musst nur evtl. einfach die Inhalte (wo)anders pflegen; und dann daraus beim Speichern statischen Inhalt erzeugen.

Hm, aber am Ende des Tages brauche ich dann doch eine dynamische Umgebung, wo die Inhalte geflegt werden können. Das verschiebt doch nur die Problematik und am Ende habe ich zwei Ökosysteme zu pflegen. Den einzigen Vorteil hier sehe ich in der Entkopplung zwischen Contentpflege und Contentdarstellung.

17.05.2019 - 13:06 Uhr

Vielen Dank für Eure Antworten. Ich muss mir mal Gedanken machen, ob Azure für das Projekt überhaupt die geeignete Plattform ist. Ich finde Azure eine sehr interessante Plattform und wollte mal etwas Erfahrungen sammeln.

Mein Focus liegt dann aber doch mehr auf dem Sammeln praktischen Erfahrungen mit .NET Core. Wenn das in einem finanziell vernünftigen Rahmen nicht vereinbar ist, dann werde ich wohl zu klassischen Hosting-Lösungen greifen. Hier gibt es passende Angebote bereits ab 4 Euro. Wobei ich für das Sammeln von Erfahrungen mit der Plattform durchaus bereit wäre, den einen oder anderen Euro mehr zu investieren. Auch um mal mit anderen Lösungsansätzen in Berührung zu kommen.

Ein einfaches "Lift and Shift" ohne Anpassungen an die Cloud Technologien wird immer teurer ablaufen.
Immer.

Das ist mir schon klar. Grundsätzlich bin ich hier schon offen für alternative Ansätze. Nur welche die geeigneten sind, ist mir nicht so ganz klar. Ich werde mich hier bei Gelegenheit noch einmal etwas intensiver befassen.

Mein Blog oder azuresaturday.de haben wir jedoch mit statischen Generatoren gemacht.
Mein Blog mit einer eigenen Engine und azuresaturday.de mit Hugo.

Statische Generatoren erzeugen durch ein Template HTML Code, das dann sehr Kostengünstig auf einem Blob Storage liegen kann.

Was in meinem Fall eher gegen eine statische Webseite spricht, ist der Einsatz einer kleinen Benutzerverwaltung zur Inhaltspflege. Als Ersteller der Webseite möchte ich mich nicht um die Contentpflege kümmern.

Derzeit hoste ich noch auf einem virtuellen Windows 2008 R2 Server. Etwas ändern muss sich über kurz oder lang definitiv. Perspektivisch ist die Umgebung jedenfalls nicht.

teebeast

15.05.2019 - 13:35 Uhr

Hallo zusammen,

ich habe immer wieder mal - mit wenig Erfolg - mir überlegt, wie ich eine bestehende Webseite nach Azure bekommen könnte bzw. ob Azure für mich überhaupt eine geeignete Wahl ist. Vor allem aus dem finanziellen Aspekt heraus. Gerade hier habe ich das Gefühl, dass man ganz schnell in finanzielle Dimensionen vorstößt, die für ein Freizeitprojekt nicht akzeptabel ist.

Nun kurz mal zur Bestandsaufnahme:

  • Es kommt aktuell ASP.NET MVC 5, EF6 sowie MySQL als auch SqlCE zum Einsatz
  • Für Daten werden ca. 1 GB benötigt - hauptsächlich Galeriebilder
  • Die Datenbanken haben jeweils eine Größe von ca. 20 MB. Hier werden hauptsächlich Informationen zu Mannschaften, Spielpläne als auch News und Termine vorgehalten
  • Die Zugriffzahlen auf die Webseite sind vernachlässigbar (< 100 pro Tag)

Sofern aus Eurer Sicht Azure in Frage kommen würde, was wäre dann die bei Azure zu wählenden Komponenten, um möglichst preisgünstig zu sein? Im Zuge der Umstellung wird auch eine Migration des Projektes nach .NET Core 2.2+ erfolgen. Bei der Wahl der Datenhaltung bin ich flexibel.

Über persönliche Erfahrungen sowie Vorschläge als auch Links zum Thema Azure oder auch Migration würde ich mich freuen. Gerne auch, ob Euch die Komplexität des Angebotes ebenfalls erschlägt.

teebeast

05.04.2019 - 08:57 Uhr

Das gleiche Problem hatte ich vor paar Tagen auch. Ich hatte ein SDK der Version 2.2.2xx installiert. Als ich dann auf der Webseite von Microsoft geschaut habe, war die aktuellste Version aber eine 2.2.1xx. Eventuell war das eine Preview-Version die mit der Preview von VS 2019 installiert wurde. Die eine Version deinstalliert, die andere installiert und schon hat es funktioniert.

11.02.2019 - 12:32 Uhr

Servus,

Telerik liefert für seine Komponenten den Quellcode mit. Ist m.E. in jeder Lizenz enthalten. Bei WPF werden unabhängig vom Quellcode die Style-Dateien als Ressourcen mitgeliefert. Man kann also ganz entspannt nachschauen. Außerdem gibt es auch einen Color Theme Generator für die WPF-Komponenten. Vielleicht hilft Dir der bei der Suche weiter - oder zumindest beim Stylen.

07.12.2018 - 09:31 Uhr

Ich erhoffe mir langfristig, dass es zukünftig nur noch eine Render-Engine gibt - und das als Open Source, sofern sie das nicht schon ist. Sollte bei der Entwicklung einiges einfacher machen.

Dominanz- und Monopolprobleme seh ich erst einmal nicht so sehr, schließe sie aber nicht aus. Auf der Engine kann jeder sein eigenes Programm drumherum aufsetzen. Hier sehe ich genügend Spielraum für Philosophien und Raum für Abgrenzung, um ein gesundes Maß an Browser-Konkurrenz zu haben.

15.11.2018 - 11:11 Uhr

In meinen Augen scheint das ein falscher Ansatz zu sein. Du scheinst nicht das MVVM-Pattern zu verwenden, dass für ein optimales Arbeiten mit WPF verwendet werden sollte. Auf Events von WPF zu hören, dass etwas fertig gerendert wurde, scheint mir in diesem Fall der falsche Ansatz zu sein.

Mein persönlicher Lösungsansatz wäre eine IsBusy-Eigenschaft im ViewModel, welches gegen die Visibility des LoadingScreen-Controls gebunden wäre. Somit kann ich aus Routine für das Laden von Daten die Bearbeitbarkeit der Oberfläche steuern.

10.08.2017 - 16:49 Uhr

Hallo Manullino,

ich habe die Extension selbst schon genutzt und habe mich an der Schreibweise nicht gestört - sie ist recht knapp gehalten. Hinter lex:Loc steckt ja etwas Logik, welche anhand eines Strings aus einer definierten Resource die Übersetzung zieht.

Nach dem Du nur einen String definieren möchtest, müsstest Du bei der Initialisierung des Controls den String aus Content auslesen und durch die Übersetzung ersetzen. Für Label ist das noch einfach, aber es gibt Controls, die mehr als ein übersetzbares Property haben. Ferner müsste der Mechanismus für jedes verwendete Control geschrieben werden. Ich weiß nicht, ob der Aufwand einschließlich der einhergehenden Fehleranfälligkeit und Wartbarkeit zum gewünschten Ergebnis stehen würde. Ich bezweifle das eher sehr.

teebeast

06.06.2016 - 15:58 Uhr

Nach ein paar frustrierenden Stunden saß das Problem vor dem Computer selbst. Es wurde ein falsches Property für die Validierung verwendet. Derer gibt es leider bei Bindungen zuhauf und mir ist es nicht aufgefallen, da mich die Spur auf eine falsche Fährte geführt hat.

<local:TestTextBox Text="{Binding ElementName=Me, Path=TestValue, ValidatesOnDataErrors=True, Mode=TwoWay}" />

@MrSparkle: Ich respektiere die hier geleistete Arbeit vollumfänglich. Nur macht der Ton die Musik und einen Fehler da zu suchen, wo ich ihn ausgeschlossen habe, ist nicht hilfreich und zielführend. Da ist keine Antwort die bessere Antwort.

Trotzdem viel Dank für Eure Hilfe.

06.06.2016 - 09:13 Uhr

Wenn dem so wäre, hättest du das problem wahrscheinlich nicht.

@FZelle, ich nehme das jetzt etwas persönlich, hier meine fachliche Kompetenz in Frage zu stellen. Diesem Forum-Post gehen zwei Stunden Google-Suche voraus, bevor ich die Community hier mit meiner doch sehr speziellen Frage belästige. Würdest Du die Implementierung von IDataErrorInfo kennen und verstehen, dann hätte Dir spätestens an der XAML-Implementierung auffallen müssen, dass die Implementierung des ViewModels irrelevant ist, da in beiden Fällen gegen das gleiche Property aus dem ViewModel gebunden wird. Das Triggern für die Validation sollte aber aus der View bzw. dem Control ausgelöst werden. Einmal funktioniert es und einmal nicht. Also muss das Problem meines Wissens nach in der Implementierung von individuellen DependenyProperties liegen.

Anbei die Implementierung des ViewModels. Belehre mich eines besseren und ich verneige mich und ziehe meinen Hut.

    public class TestViewModel : INotifyPropertyChanged, IDataErrorInfo
    {
        private int? _testValue;

        public int? TestValue
        {
            get { return this._testValue; }
            set
            {
                if (this._testValue != value)
                {
                    this._testValue = value;
                    this.RaisePropertyChanged(nameof(this.TestValue));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void RaisePropertyChanged(string propertyName)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public IDictionary<string, string> ValidationErrors { get; } = new Dictionary<string, string>();

        public string this[string columnName]
        {
            get
            {
                this.ValidationErrors.Remove(columnName);

                string errorText = null;

                switch (columnName)
                {
                    case nameof(this.TestValue):
                        errorText = "TESTFEHLER";
                        break;
                }

                if (!string.IsNullOrWhiteSpace(errorText)) this.ValidationErrors.Add(columnName, errorText);

                return errorText;
            }
        }

        public string Error { get; } = null;
    }

Es wäre schön, zumindest einen Hinweis zu bekommen, wo ich mit meiner Suche ansetzen muss. Die Websuche hat leider keine brauchbaren Ansätze geliefert. Danke.

03.06.2016 - 12:10 Uhr

Hallo,

ich habe das Problem, dass die Methode für die Validierung einer Eingabe nicht getriggert wird. Hierzu habe ich mal eine Testimplementierung gemacht, um das etwas genauer zu verdeutlichen. Das Interface IDataErrorInfo ist im ViewModel korrekt implementiert und wird hier nicht exemplarisch dargestellt.

    public class TestTextBox : TextBox
    {
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(int?), typeof(TestTextBox),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ValueChangedCallback));

        public TestTextBox()
        {
            this.LostFocus += (sender, args) =>
            {
                int value;
                if (string.IsNullOrWhiteSpace(this.Text)) this.Value = null;
                else if (int.TryParse(this.Text, out value)) this.Value = value;
                else this.Value = null;
            };
        }

        private static void ValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as TestTextBox;

            if (control == null) return;

            control.Text = string.Format("{0:F0}", control.Value);
        }

        public int? Value
        {
            get { return (int)this.GetValue(ValueProperty); }
            set { this.SetValue(ValueProperty, value); }
        }
    }

Im Xaml funktioniert die Bindung gegen Text, gegen Value aber nicht.

<local:TestTextBox Text="{Binding ElementName=Me, Path=TestValue, NotifyOnValidationError=True, Mode=TwoWay}" />
<local:TestTextBox Value="{Binding ElementName=Me, Path=TestValue, NotifyOnValidationError=True, Mode=TwoWay}" />

Hat jemand eine Idee, was in der Implementierung fehlt, sodass es auch mit dem Property Value funktioniert?

Ronny

07.03.2016 - 22:53 Uhr

Hi,

wie Abt schon geschrieben hat, muss eine Klasse, die über Application.Run aufgerufen wird, von Form erben. Das tut Deine Klasse BorderedPhoto aber nicht. Deswegen funktioniert es nicht.

09.01.2016 - 11:07 Uhr

Hallo,

man kann kleinere Objekte problemlos serverseitig in der Session ablegen. Die Klasse sollte aber mit dem Attribut [Serializable] dekoriert werden, da die Session serverseitig auch serialisiert werden kann - je nach Konfiguration.

this.Page.Context.Session["Key"] = instance;
HttpContext.Current.Session["Key"] = instance;

Über diesen Mechanismus kann man auf diese Objekte wieder zugreifen. Beim Zerstören der Session werden alle Einträge ebenfalls gelöscht, man kann dies aber auch explizit machen.

Deine Klasse könnte eine Methode ForSession() implementieren, die dafür sorgt, dass eine für die Session vorgesehene Klasse über den Konstruktor befüllt wird. Dann kann diese auch readonly sein.

Grüße

P.S.: Das Beispiel gilt für ASP.NET Forms, ASP.NET MVC funktioniert aber ähnlich.

23.11.2015 - 18:25 Uhr

Hi,

die Klammerung Deiner for-Schleife fehlt. StartBackup wird nur einmal ausgeführt. Grundsätzlich würde ich Dir empfehlen, dass Du der Methode StartBackup die zu kopierenden Elemente in einer Liste übergibst und diese dann über die einzelnen Elemente iteriert.

14.11.2015 - 09:39 Uhr

Hi,

also für mich schaut der Text eher nach "\r\n" aus. Sonst würde im Text nicht "\r\n" stehen und die Umbrüche würden einfach ignoriert werden, wenn es sich tatsächlich um ein Problem mit der Darstellung der Zeilenumbrüche handeln würde.

16.06.2015 - 18:19 Uhr

Hi,

also grundsätzlich reicht es aus, in der for-Schleife die Werte aufzusummieren und danach die Summe mit der Zahl zu vergleichen. Somit kannst Du komplett auf die Variable isOk verzichten.

Ferner hätte ich die do-while-Schleife durch eine for-Schleife abgebildet, aber das ist Geschmacksache.

20.01.2015 - 12:37 Uhr

Prüfe doch mal, welches Kompatibilitätslevel Deine Datenbank hat. Wenn die von einer älteren Datenbank migriert wurde, dann kann es sein, dass sie die Funktionen nur der alten Version unterstützt. Du kannst das Kompatibilitätslevel über die Eigenschaften der Datenbank verändern.

Keine Garantie, dass es das tatsächlich ist.

Gruß,
Ronny

22.03.2013 - 11:15 Uhr

Hi,

versuche doch einfach mal, Dich auf Stellen zu bewerben. Mein Auftraggeber sucht derzeit händeringend einen Entwickler, bekommt aber derzeit keine wirklich passenden Bewerbungen und die Anforderungen sind nicht wirklich hoch angesetzt. Er bekommt sogar Bewerbungen aus der PHP- bzw. Java-Ecke - ohne das abzuwerten. Aus meiner Sicht wäre dann eher die Gehaltsvorstellung der Knackpunkt, vor allem wenn man sich bereits auf einem recht hohem Niveau befindet. Hier zählt dann sicherlich Qualifikation und vor allem Berufserfahrung.

Prinzipiell würde ich sagen, dass der Arbeitsmarkt derzeit ganz gut ausschaut und man als "Plattformwechsler" sicherlich gute Chancen auf einen Job hat. Vor allem hast Du ja schon Erfahrungen mit .NET sammeln können.

18.03.2013 - 13:11 Uhr

Hi,

entferne doch mal im Quellcode die Ableitung von der Basisklasse. Wird nicht benötigt, da hier die Basisklasse in der XAML-Definition verwendet wird. Alternativ kannst Du die Ableitung auch in MetroWindow ändern.

11.02.2013 - 10:15 Uhr

Hallo bernado,

ein klassiches Vorgehen, um den letzten Tag im Monat zu bekommen, ist einfach vom 1. des Folgemonats einen Tag abzuziehen.

Gruß,
Ronny

14.12.2012 - 09:00 Uhr

Hi,

das Problem habe ich auch, sehe es persönlich aber nicht so als allzu kritisch, da es mir persönlich wichtiger ist, dass die Abhängigkeiten zwischen den Klassen nicht existieren. Abhängigkeiten zu Assemblies sind relativ leicht angepasst.

Meines Wissens könnte man die abhängigen Assemblies nur dadurch auflösen, in dem diese dynamisch registriert werden und die Konfigurationsklassen für Unity ermittelt und aufruft. MEF bietet hier einen möglichen Ansatz.

Ich fand den Aufwand bisher immer etwas übertrieben, vor allem da ich mit der Technik bisher relativ kleine Projekte umgesetzt habe. Trotzdem bin ich sehr auf Lösungsansätze gespannt. Vielleicht setzte ich dann sowas mal um, der Übung halber.

Grüße,
teebeast

30.10.2012 - 08:26 Uhr

Hallo Maruu,

In den letzten Tagen habe ich viel über HTML 5 und Silverlight gelesen. Der Ansatz von HTML 5 gefällt mir gut (Plattformübergreifend, Stadardisiert) aber ich scheue mich noch davor es als universelle Wunderwaffe zu verwenden. Im Bereich normale Webseiten mag HTML 5 die Lösung sein, für (größere) Businessanwendungen bezweifle ich das aber.

Deine Abneigung gegenüber Javascript kann ich durchaus nachvollziehen. Ich arbeite nun seit über 4 Jahren in der ASP.NET-Welt und habe immer noch eine gewisse Abneigung gegen Javascript. Inzwischen habe ich mich mit Javascript arrangiert. HTML ist durchaus für größere Businessanwendungen geeignet. Ich selbst arbeite an solch einer Lösung mit. Im Endeffekt vermeiden wir Javascript da, wo es geht. Somit ist der bei uns in Verwendung befindliche Anteil von Javascript recht gering und relativ einfach gestrickt.

Ich kann nur empfehlen, dass Ihr ein kleineres Projekt mit HTML umsetzt und einfach Erfahrungen sammelt. Es gibt viel zu lernen und die richtigen Konzepte für die Umsetzung einer Businessanwendung in HTML kommen erst mit den Erfahrungen.

Grüße,
Ronny

PS.: In Javascript ist es durchaus möglich, mit Klassen zu arbeiten. Der Ansatz von Javascript verleitet nur sehr gerne, ohne Klassen zu arbeiten.

27.10.2012 - 21:15 Uhr

Hallo dat Levion,

ich habe mich zwar selbst damit noch nicht befasst, aber es gibt hier ein paar gute Tutorials von Microsoft zu diesem Thema. Ich kann auch den ADO.NET Blog hierzu empfehlen.

Code First Migrations

Gruß,
Ronny

24.10.2012 - 14:36 Uhr

Hallo Hannes,

bei Silverlight wäre ich sehr vorsichtig. So wie es sich abzeichnet, wird Silverlight 5.1 die letzte Version sein - auch wenn sie noch recht lang gepflegt wird. Ich befürchte, dass die Browserunterstützung über die Zeit immer schlechter werden wird. Ich persönlich würde die Finger davon lassen - leider. Finde es eigentlich eine gute Idee. Vielleicht kommt später noch einmal etwas ähnliches, was dann auf der Basis von Windows 8 Apps aufgesetzt wird.

Um Apple und Co zu erreichen, wäre auch eine Überlegung auf Mono zu gehen. Sonst kann ich als zusätzliche Alternative zu einem Clientsystem nur eine Web basierte Lösung empfehlen. Hier bietet sich ASP.NET (MVC) durchaus an. Ich persönlich habe mit ASP.NET schon sehr gute Erfahrungen gemacht und mein Auftraggeber betreibt inzwischen schon ein sehr großes Intranet mit diversen Anwendungen auf dieser Basis. Die Browserkompatibilität ist aber ein Graus, wird aber meines Erachtens von Jahr zu Jahr immer besser. Tendentiell würde ich hier ganz klar auf HTML5 mit CSS3 setzen. Da gibt es inzwischen auch schon eine gute Auswahl an Browsern, die auf allen möglichen Systemen laufen.

Grüße,
Ronny

30.08.2012 - 17:35 Uhr

Hast Du die Klasse auch an den DataContext gebunden? Sonst weiß er natürlich nicht, worauf er zugreifen soll.

this.DataContext = this._myOverlay;
25.08.2012 - 15:36 Uhr

Ich schreibe mal ein wenig meine Erfahrung bzw. meine Denkweise zu den Themen:

Arbeiten unter Druck
Kennt wohl jeder sehr gut. 😁 Ich denke, dass man vieles davon vermeiden kann, wenn man den Aufwand vernünftig abschätzt und diesen auch vernünftig den Kunden bzw. Vorgesetzten argumentieren kann. Funktioniert in kleinen Firmen meist weniger gut, da man etwas mehr Flexibilität zeigen muss, aber man kann trotzdem lernen, die Stresssituationen auf ein Minimum zu reduzieren. Aber das muss der Chef lernen.

Übung und Training
Das schaut bei mir so aus, dass ich sehr viel Blogs lese. Hier informiere ich mich über neue Technologien bzw. Best Practice sowie Lösungsansätze. Für mich ist es wichtig, Dinge überhaupt einmal gesehen zu haben, damit man weiß, dass es sie gibt. Wenn ich die Möglichkeit habe, versuche ich solche Dinge in Projekte mit einfließen zu lassen. Klappt aber nicht so oft - zumindest nicht unmittelbar.
Der zweite wichtige Punkt aus meiner Sicht ist der Erfahrungsaustausch mit anderen Kollegen. Das kann sehr banal sein, z.B. wie man ein kniffliges Problem gelöst hat bzw. eine Erfahrung gemacht hat, die andere wissen sollten. Gerade sehr wichtig bei Technologien, die man nur am Rand benutzt und etwas unsicher ist.

Mentoring
Das Begleiten von unerfahrenen oder auch neuen Programmieren finde ich sehr wichtig. Wenn das Firmen nicht vorleben, sollte man sich als junger Programmiere wenn möglich an einen alten Haudegen hängen, zu dem man einen guten Draht hat. In der Regel werden diese ihr Wissen gerne teilen. Zumindest habe ich hier sehr gute Erfahrungen gemacht. Hatte hier in meinen jungen Jahren auch einen Mentor, der mir die OOP nahe gebracht hat.
Selbst wenn man ein erfahrener Programmierer ist, kann man sich untereinander immer noch etwas beibringen. Jeder hat seine Spezialgebiete, sodass man immer etwas von jemanden anderen lernen kann. Ist vielleicht kein klassisches Mentoring mehr, aber für das Spezialgebiet ist man dann doch wieder "Novice".

13.08.2012 - 09:15 Uhr

Hallo Karategoldi,

also ich würde das Problem so lösen:

Wenn der obere und linke Rand beschränkt ist, dann sollte der x- bzw. y-Wert des Rechteckes negativ sein. Hier kann der Wert recht einfach mit Math.Max(0, x) gesetzt werden, sodass positive Werte erhalten bleiben. Das Rechteck schieb es dann auf eine zulässige Koordinate. Alternativ könnte man natürlich nur die Größe des sichtbaren Rechteckes darstellen. Hier muss dann noch die Länge und Breite um den negativen Wert korrigiert werden.

Bei einer Erweiterung des Zeichenraums würde ich wie folgt vorgehen:

  • Ermittle Dir einen Offset für das Rechteck außerhalb des Zeichnungsbereiches: var xOffset = Math.Max(0, -x); // nur negative Werte - also außerhalb Deines Zeichnungsbereiches erzeugen einen Offset
  • Addiere den Offset zur Breite Deines Zeichnungsbereiches
  • Addiere den Offset zu allen x-Koordinaten von Deinen Objekten - auch dem neuen Objekt

Voila. Das ganze noch mit der y-Koordinate, dann sollte es passen.

Gruß,
Ronny

03.06.2012 - 19:28 Uhr

Also ich bin schon der Meinung, dass der Quereinstieg funktionieren kann - auch mit 33 Jahren. Ich habe meinen Quereinstieg mit 25 Jahren gemacht. Inzwischen habe ich zehn Jahre Berufserfahrung und bin seit vier Jahre selbständig. Einen IT-Abschluss habe ich bis heute nicht.

Grundsätzlich braucht man dafür schon ein wenig Glück, dass man den entsprechenden Arbeitgeber findet. Meine Erfahrungen zu diesem Zeitpunkt gingen über grundlegende Kenntnisse nicht hinaus. Mit Understatement und dem Fachwissen aus meinem gelerntem Beruf hatte ich die nötige Zeit, mich in der Firma zu beweisen. Gerade in den ersten Jahren lernt man so dramatisch viele Sachen, dass man schauen muss, dass man durchhält.

Ich persönlich würde Dir empfehlen, Dir nicht unbedingt eine Softwarefirma zu suchen, sondern eine Firma, die eine kleine Programmierabteilung hat. Hier kann man sich die notwendigen Erfahrungen aneignen, die man dann für ein Sprungbrett in eine Softwarefirma nutzen kann - sofern das überhaupt ein Ziel ist. Die Anforderungen sind hier in der Regel deutlich geringer.

Also nur Mut und hör Dich mal um. Sprich mit so vielen Leuten wie möglich über Deine Idee. Vielleicht bekommst Du den notwendigen Tipp. Abschließend kann ich nur sagen, dass Du wohl jetzt schon deutlich mehr drauf hast als ich zur Zeit meines Quereinstieges.

13.04.2012 - 10:23 Uhr

Hallo Cannon,

ich habe das Problem über einen ServiceLocator gelöst, in dem die möglichen Dialoge registriert werden. Darüber hinaus verwende ich einen Service, der mir den Aufruf der Dialoge steuert. Im Endeffekt habe ich mich hierbei bei folgenden Blogeintrag inspirieren lassen, der das sehr ausführlich beschreibt.

Blog zum Thema Dialogaufrufe per MVVM

Ich hoffe, das hilft Dir weiter.

Gruss,
Ronny

27.02.2012 - 14:50 Uhr

Also ich würde das Problem etwas anders lösen:


var date = DateTime.Today.AddDays(-120);
var count = new EntitySet().Fahrzeuge.Count(f => f.UebergabeDatum.Value < date);

Da spart man sich die Date-Funktionalität des SQL-Servers.

10.02.2012 - 22:13 Uhr

Übrigens lässt sich der ViewState auch serverseitig speichern. Hierzu kann ein individueller PagePersister verwendet werden, der die Daten serverseitig hält und nur eine eindeutige Kennung in der Seite ablegt.

Standardmäßig sollte ASP.NET einen SessionPagePersister zur Verfügung stellen. Der hält die Daten aber nur eine begrenzte Zeit vor. Im Web lassen sich durchaus Beispiele für einen SqlPagePersister finden, falls das eine Option wäre.

05.02.2012 - 03:54 Uhr

Hallo mygil,

ich habe zwar keine Lösung für Dein Problem mit dem EF-Context parat, aber grundsätzlich würde ich davon abraten, dass Änderungen in einem Dialog direkt auf die EF-Entität geschrieben werden. Hier kann ich nur ganz dringend empfehlen, mit einer Kopie des Objektes zu Arbeiten bzw. die im Dialog verwendeten Eigenschaften beim Öffnen des Dialoges zu kopieren und beim Speichern wieder zu setzen.

Auf diese Weise lässt sich das Problem umgehen.

Gruss,
teebeast

05.02.2012 - 03:44 Uhr

Hallo Hans,

durch dieses Thema habe ich mich auch schon gekämpft. Vorab mal ein Buchtipp von mir:

"Building Enterprise Applications with Windows Presentation Foundation and the MVVM Model View ViewModel Pattern" von Raffaele Garofalo.

Das Buch geht nicht nur auf MVVM ein, sondern zeigt auch sehr schön, wie man eine Anwendung strukturieren kann. Es ist eines der wenigen Bücher, die es zu diesem Thema gibt. Leider.

Zu Deinem Problem zwei Dinge, die mir auffallen.1.Du musst im ViewModel INotifyPropertyChanged implementieren, damit die View mitbekommt, dass es im ViewModel Änderungen gibt.
In Deinem Fall könntest Du die Logik aus Deinem Model übernehmen.

1.Du musst das ViewModel dem DataContext der View zuweisen. Im einfachsten Fall wäre das im Konstruktor der View.

Gruss,
Ronny

29.12.2010 - 10:45 Uhr

Also ich würde mal sagen, dass Du für jedes Objekt in Deiner Liste eine eigenen Datenbankabfrage machst. Das kann nur wenig performant sein. Ich empfehle Dir folgenden Aufbau, der auch dem DRY-Prinzip folgen sollte:

public static MyObject GetMyObject(int id)
{
    // Datenbankabfrage
   if(reader.read())
   {
        return FillObject(reader);
   }
}

public static MyObjectCollection GetMyObjects()
{
   var myObjectCol = new MyObjectCollection();
   //Datenbankabfrageerstellung usw.
   while(reader.read())
   {
      myObjectCol.Add(FillObject(reader));
   }

   return myObjectCol;
}

private static MyObject FillObject(MySqlDataReader reader)
{
   var myObject = new MyObject();
   //Eigenschaften setzen
   return myObject;
}