Laden...

Forenbeiträge von JimStark Ingesamt 309 Beiträge

03.12.2020 - 16:20 Uhr

Okay vielen Dank für die Info! Hat mir sehr geholfen.

Mein Hoster unterstützt es natürlich nicht 😄

03.12.2020 - 15:15 Uhr

SMIME hat im Gegensatz zu anderen Zertifikatstypen die Besonderheit, dass man keine eigentliche Root CA benötigt, sondern den Public Key vom Signierungszertifikat im DNS hinterlegen kann, die sogenannten SMIMEA Records (=> DNSSEC).
Der Client holt sich daher anhand der DNS Informationen alles was er braucht, um die Signatur validieren zu können.

Vielen Dank für deine Antwort!
Das heißt ich erstelle mir z.B. in Powershell ein Self-Signed-Certificate.
Den public key hinterlege ich mir im DNS wie von dir beschrieben, vorausgesetzt mein Hoster unterstützt DNSSEC.
Dann checkt Outlook vom Empfänger per Abfrage ob das Zertifikat valid ist? (Also entspricht Class 1 oder?!)

Also wie hier: SMIMEA - Type 53?

02.12.2020 - 17:27 Uhr

Ich habe neulich auch was interessantes entdeckt. Ist zwar kein C# aber naja 😉
Vielleicht kennt der ein oder andere das Computerspiel Airline Tycoon aus den früheren 2000ern. Da ist mittlerweile der Quelltext verfügbar.

Hier eine Funktion ob ein spezielles Feature vorhanden ist bzw. ob die Bots bestimmte Features nutzen dürfen:


//--------------------------------------------------------------------------------------------
//Unterstützen die Roboter im aktuellen die Level ein bestimmtes Feature:question:
//--------------------------------------------------------------------------------------------
bool RobotUse (SLONG FeatureId)
{
   SLONG Level;

   //Die verschiedenen Levelstrukturen in eine Reihe bringen:
   if (Sim.Difficulty>=DIFF_TUTORIAL && Sim.Difficulty<=DIFF_FINAL) Level = Sim.Difficulty;
   else if (Sim.Difficulty==DIFF_FREEGAME || Sim.Difficulty==DIFF_FREEGAMEMAP) Level = 6;
   else if (Sim.Difficulty>=DIFF_ADDON01 && Sim.Difficulty<=DIFF_ADDON10) Level = Sim.Difficulty-DIFF_ADDON01+7;
   else if (Sim.Difficulty>=DIFF_ATFS01 && Sim.Difficulty<=DIFF_ATFS10) Level = Sim.Difficulty-DIFF_ATFS01+7+10;

   //Tabelle ermitteln für welche Level ein Feature ermittelt wird:
   const char *pFeatureDesc;
   switch (FeatureId)
   {
      //0-5 : Level im Basisspiel
      // F  : Freies Spiel
      //0-9 : Level in Addon / FlighSecurity
      //
      //"-." : Disabled
      //"xX" : Enabled
      //"!"  : Enabled, but wasn't enabled in AT 1.0
      //"?"  : Enabled, but isn't enabled in AT First Class
      //                                            Basisspiel       Addon        FlightSecu      
      //                                                012345   F   0123456789   0123456789 
      case ROBOT_USE_SABOTAGE         : pFeatureDesc = "-XXXXX" "X" "XXXXXXXXXX" "-XXXXXXXXX"; break;
      case ROBOT_USE_FRACHT           : pFeatureDesc = "------" "X" "-XXXXXXXXX" "XXXXXXXXXX"; break;
      case ROBOT_USE_WERBUNG          : pFeatureDesc = "---XXX" "!" "XXXXXXXXXX" "-XX-X-XXXX"; break;
      case ROBOT_USE_AUFSICHT         : pFeatureDesc = "----XX" "!" "----------" "----------"; break;
      case ROBOT_USE_NASA             : pFeatureDesc = "-----X" "." "---------X" "----------"; break;
....
      case ROBOT_USE_MAX20PERCENT     : pFeatureDesc = "XXXXXX" "!" "XXXXXXXXXX" "XXXXX-XXXX"; break;
      case ROBOT_USE_TANKS            : pFeatureDesc = "------" "." "----------" "--------XX"; break;
      case ROBOT_USE_DESIGNER         : pFeatureDesc = "------" "?" "----------" "---XX-XX--"; break;
      case ROBOT_USE_DESIGNER_BUY     : pFeatureDesc = "------" "." "----------" "----X--X--"; break;

      default:
         TeakLibW_Exception (FNL, ExcNever);
   }

   return (pFeatureDesc[Level]!='-' && pFeatureDesc[Level]!='.') && (!bFirstClass || pFeatureDesc[Level]!='?');
}


Die Lösung fande ich irgendwie sehr interessant 😁 Generell ist da der halb deutsche Quelltext sehr lustig zu lesen.

Siehe:
AirlineTycoon/src/Player.cpp

30.11.2020 - 18:54 Uhr

Hey,
ich denke einige kennen sich in diesem Themengebiet recht gut aus deswegen mal eine etwas andere Frage:
Als Vorbeugung vor Scamern und für sensiblere Daten möchte ich gerne für uns E-Mail Zertifikate erstellen und nutzen, damit wir Mails signieren und ggf. verschlüsseln können.
Jetzt kann ich ja bei verschiedenen Anbietern welche für einzelne Mailadressen/Abteilungsadressen erstellen und validieren lassen und z.B. einfach in Outlook importieren.
Ich kenne aber viele Unternehmen die selbst Zertifikate ausstellen. Wie funktioniert das dann und mit der Gültigkeit? Ich schätze ich brauche eine Art Rootzertifikat damit ich als Aussteller zertifiziert bin oder? Welche Infrastruktur brauche ich dafür und wieviel kostet sowas ca.? Und ab wann rentiert sich sowas überhaupt?

Viele Grüße!

26.11.2020 - 17:48 Uhr

Aus Interesse, WBB oder auch phpBB ist doch eine vollständige Forensoftware. Wie kann das Front-End dann geich bleiben? Das Theme ans neue Backend anpassen oder wie? Ist das nicht viel mehr Aufwand als gleich ein ganz neues zu machen?

23.11.2020 - 11:53 Uhr

Ja, der braucht aber auch ein DateTime. Mit dem extra Feld geht es jetzt.

22.11.2020 - 15:45 Uhr

Wenn mich nun nicht alles täuscht dann wird da mit UTC gerechnet und die Textbox gibt dir dann Ortszeit an, deswegen die 2h Unterschied.

Ja genau daran lag es! Ich habe es jetzt über ein weiteres Feld im ViewModel gelöst anstelle des Convertes. Damit geht es. Danke euch beiden!


        private DateTimeOffset _Date;

        public DateTimeOffset Date
        {
            get { return _Date; }
            set { _Date = value;
                OnPropertyChanged(nameof(Date));
            }
        }

        public DateTime DateLocal
        {
            get
            {
                return Date.UtcDateTime;
            }
            set
            {
                Date = DateTime.SpecifyKind(value, DateTimeKind.Utc);
            }
        }

21.11.2020 - 18:48 Uhr

Hi,

ich habe folgendes Problem:


// ViewModel:
        private DateTimeOffset _Date;

        public DateTimeOffset Date
        {
            get { return _Date; }
            set { _Date = value;
                OnPropertyChanged(nameof(Date));
            }
        }

// WPF:
      <TextBox Text="{Binding Date, StringFormat=d}" />

Das Datum wird mir in der Textbox korrekt angezeigt (DD.MM.YYYY).
Wenn ich das nun ändere (03.01.2020 in 02.01.2020) und abspeichere, wird das Datum -1 Tag genommen (01.01.2020). Ich denke das liegt daran dass die Stunde standardmäßig Null ist und an der internen Konvertierung von DateTime in DateTimeOffset durch das StringFormat(?).

Entferne ich das StringFormat erscheint mir das Datum als z.B. "01.01.2018 22:00 +00:00". Wenn ich jetzt das Datum ändere und übernehme stimmt es.
Hat da jemand einen Tipp damit das trotzdem funktioniert? Also das ich das kurze Datumsformat behalten kann?

21.11.2020 - 09:48 Uhr

Jedoch möchte ich jetzt einen guten Brute Force Sortieralgorithmus schreiben, welcher nicht zufällig mischt, sondern nacheinander alle Möglichkeiten, die es gibt probiert.

Das kannst du mit ein paar Schleifen selber zusammen bauen oder vielleicht hilft das: Enumerable.Zip Methode

19.11.2020 - 08:19 Uhr

Für dich erscheint es aber so, dass das warten auf eine async Methode (await) dazu führt, dass diese im Hintergrund ausgeführt wird und der Verarbeitungsschritt dann an den Rückgabepunkt zurückspringt.
Insofern ist es wunderbar möglich await's untereinander zu schreiben.

In diesem Beispiel, bei AddCustomerToDb: Wenn der Task "AddCustomerToDb" abgearbeitet ist, springt die Ausführung wieder zu dieser Zeile und die variable customer steht zur verfügung. Danach wird "AddCustomerAddress" abgearbeitet.
Also für den Programmierer kein Unterschied zu sequentieller Programmierung.


public async Task Test(){
   var customer = await GetCustomer(...);
   await AddCustomer(customer); // führt zu CustomerHasChanged = true
   await AndereFunktion(...);
   model.Name = "...";
   syncMethode(...);
   CustomerHasChanged = false;
}

Angenommen ich habe eine Methode wie in dem Beispiel. Verstehe ich das richtig dass nicht garantiert wird dass die Methoden in dieser Reihenfolger ausgeführt werden wenn keine Abhängigkeiten bestehen? Also in meiner Anwedung habe ich das Problem, ich arbeite mehrere Tasks mit await ab. Danach setzte ich CustomerHasChanged = false. Der ist dann aber true, was irgendwie bedeutet dass die Tasks noch laufen (führen zu CustomerHasChanged=true), das setzen aber schon abgearbeitet ist.

18.11.2020 - 20:37 Uhr

Super, vielen Dank! Genau was ich gesucht habe.

Ich verstehe da aber den Syntax nicht ganz oder wie das genau funktioniert:



public async Task AddCustomer()
{
  var customer = await AddCustomerToDb(); //Task<Customer>
  await AddCustomerAddress(customer, address); // Task 
  await AddCustomerToProject(customer, 1); // Task
}

//vs.

public async Task AddCustomer()
{
   return Task.Run( () => {...}; // Task zurück
}



Den zweiten Fall verstehe ich, da gebe ich einen Task zurück. Wenn ich die MS Docs richtig verstanden habe ist "await xyz()" auch vom Typ Task. Wie funktioniert das intern das da was returned wird, auch wenns mehrere Tasks gibt bzw wenn ein übergeordneter Task draus gemacht wird...?

18.11.2020 - 19:04 Uhr

Hi Leute,

bisher dachte ich die sauberste und einfachste Benutzung von Tasks in WPF ist z.B.:


// Beispiel Command an Button gebunden:
public async void AddCustomerExecute(){
   await AddCustomer(...);
...
}

Also dass die Oberfläche weiterläuft und auf die Beendigung wartet. Ich verstehe nur nicht ganz wie man die Anwendung am besten entwirft wenn Tasks abhängig von Tasks sind.

Beispiel:


public async void AddCustomerExecute(){
   await AddCustomeViewModel(...);
...
}

public Task AddCustomerViewModel(...){
// in dieser Funktion werden mehrere Tasks ausgeführt.
// async ohne Task sollte es so aussehen:
var result = await GetResults(...);
...
await AddCustomerToDb(...);
}

// Diese Funktion ist vorgegeben:
public Task AddCustomerToDb(...){
}

Wie gestalte ich nun die AddCustomerViewModel() Funktion, da ich ja z.B. in einem Task.Run( () => {...}) kein await nutzen kann? Mit Wait() und Result,.. ?

Ich hoffe man versteht was ich meine 😁 Und wo ist eigentlich Abt?

12.11.2020 - 17:35 Uhr

Man könnte das ganze auch über gRPC verbinden. Dann hätte man eine einheitliche Schnittstelle. Könnte aber sein dass das für euch etwas übertrieben ist, da ich denke dass dein Projekt was zusammengeschustertes für einen Arbeitsplatz ist 😁

11.11.2020 - 11:49 Uhr

Was erwartest du jetzt? Dass jemand deine komplette Anwendung analyisiert? 😄
Dir fehlen massiv Kenntnisse in C#-Grundlagen und WPF.
Ich würde mich erstmal da dran machen: [Artikel] MVVM und DataBinding

09.11.2020 - 17:42 Uhr

Wo ist jetzt genau das Problem?

Sowas zum Beispiel?


public class Sendung
{
     public double Gewicht { get; set;}
     public int Zone { get; set;}
     public double Preis { get; set;}
}


Damit erstellts du dir eine Liste (List<Sendung>) und suchst dir mit ner Linq Abfrage das passende raus. Die Liste kannst du dann auch serialisieren und abspeichern damit man sie ändern kann.

09.11.2020 - 12:05 Uhr

Soweit so gut - funktioniert auf der VM...aber nicht auf dem Rechner des Kunden. Da bricht das SDK-Setup ab (scheint Visual c++ redestribultibles nicht installieren zu können, da die schon drauf sind?).

Also ist dein Problem jetzt die Installation des SDK auf dem Kundenrechner? Bricht das ganze Setup ab?

08.11.2020 - 19:48 Uhr

zur Drei-Schichten-Architektur:
"Die Präsentationsschicht übernimmt die Aus- und Eingabe der Daten": Stimmt in meinem Fall nur bedingt. Die Methode "Berechne0_5" könnte bspw. mitten im Flug feststellen, dass der rechte Treibstofftank leer wird und das rechte Triebwerk ausgeht. In diesem Fall würden im Monitor EICAS Warnmeldungen erzeugt (Canvas wird verwendet) und im gleichen Monitor ändert sich die Grafik der Drehzahl (BitmapImage wird verwendet). Der Autopilot (den ich bisher schon mit Javascript programmiert habe) ist ebenso eine Option im Hintergrund das Flugzeug zu steuern (x- und y-Achse), welches wiederum Änderungen im ND-Monitor zur Folge hat.

Das ist dann von dir Falsch entworfen, wenn du in deiner Logik etwas abhängig von der Präsentation machst. Das wäre so wie wenn du in irgendeiner komplexen Methode auf "Form1.txtPreis.Text" zugreifen würdest. Das sollte alles komplett in deiner Klasse stattfinden. Der Präsentationsschicht wird dann das zur Verfügung gestellt was sie braucht und umgekehrt.

Nachdem innerhalb der Klassen soweit alles lief, wollte ich auf Felder einer anderen Klasse die public sind, zugreifen, was aber nicht geht ("in diesem Kontext nicht vorhanden"). Ich glaube immer mehr, dass ich in meinem Fall (fast) alles in eine Klasse schreiben sollte.

Das glaube ich nicht, vorallem wenn es so umfangreich ist.
Du kannst die Referenz einer Klasse einer anderen mitgeben und darauf zugreifen.

Pseudo-Beispiel:


public Simulator()
{
     auto = new Auto()
     werkstatt = new Werkstatt(auto)
}

06.11.2020 - 15:25 Uhr

Mein Vorschlag ist aber auch keine Logik in dem Sinne, sondern eine Art selbst gebautes Event-Binding, um das ViewModel über View-Änderungen zu informieren, ohne dass das ViewModel dabei von der View abhängig ist.
Wenn Du darauf verzichten willst, kannst Du aber auch die genannten Alternativen Behavior oder AttachedProperty nutzen, damit kannst Du sozusagen den Code "auslagern".
Es bleibt dann immer noch eine Art CodeBehind, aber es ist unabhängig von der konkreten View und kann wiederverwendet werden.

Danke für deine Tipps!

Verstehe ich das richtig, ich abonniere mir im MainViewModel z.B. OnServicesLoaded um dann darin z.B. die ViewModels der Objekte usw. initalisieren zu können? Das Event trigger ich dann von der App.xaml.cs wenn ich meine License-, Db-,... Services erstellt habe. Also damit ich Code im Konstruktor im ViewModel vermeide?

06.11.2020 - 15:07 Uhr

Bisher dachte ich, dass alle Felder/Methoden mit "public" aus anderen Klassen zugegriffen werden kann. Dies funktioniert leider nicht so wie gedacht, wie ich über das Internet erfahren habe. Ob es in meinem Fall besser wäre dieses Programm mit einer einzigen Klasse zu bauen, ist meine Hauptfrage an euch.

Wieso funktioniert das nicht?

Ich weiß nicht was du vorhast, aber vielleicht wäre es besser z.B. eine Master Simulator-Klasse zu haben und darin unterschiedliche Unterklassen (Triebwerk, kp...). Dann kann jede Klasse den Zugriff auf andere Klassen bekommen, den sie brauchen.

Du solltest dir mal [Artikel] MVVM und DataBinding anschauen.

05.11.2020 - 20:17 Uhr

Hm okay. Ich habe hier nur mal gelesen dass in der Codebehind am besten gar nichts stehen soll.

Wäre es dann sauberer in der Startup-Methode (z.B. Startup="Application_Startup") im app.xaml Code-Behind
meine Datenbankverbindung aufzubauen, MainWindow erstellen, VM übergeben, usw. Also ich verwalte meine "Services" derzeit alle im MainViewModel und übergebe die per DI an die anderen VMs.

05.11.2020 - 19:00 Uhr

Hey,

ich gebe meinem Window im XAML Code das ViewModel.


    <Window.Resources>
        <ResourceDictionary>
            <local:MainViewModel x:Key="vm"/>
        </ResourceDictionary>
    </Window.Resources>

Das Problem ist jetzt, im Konstruktor kann es sein dass ein Dialog aufgerufen wird (mit ShowDialog(), also der wartet). Das passiert auch im Designer.

Gibt es da eine Möglichkeit wie z.B. sowas in der Art:


#if DESIGNER 

Also dass er den Teil überspringt wenn er im Designermodus ist. Mit Debug ist es mir zu umständlich da ich es auch dort testen muss.

Viele Grüße

30.10.2020 - 17:25 Uhr

Ja, in dem Beispiel nutze ich aber LiteDB, welches keine asynchronen Methoden zur Verfügung stellt. Das ist nur um den Interface gerecht zu werden.

30.10.2020 - 15:21 Uhr

Ich würde dir raten erstmal C# und .NET Grundlagen zu lernen und dann dich an WPF ran wagen.

Bzgl. Visual Basic: Gute und schlechte Nachrichten für Visual-Basic-.NET-Entwickler

30.10.2020 - 13:02 Uhr

Wenn es hier über sehr einfache Datenstrukturen (einfache Key-Value Paare) hinausgehen soll, dann müsstest du wahrscheinlich eine Schnittstelle bereitstellen, die es dem Plugin erlaubt Tabellen zu erstellen/modifizieren/löschen. Wenn die Schnittstelle von einem Plugin angesprochen wird, kannst du die Tabellennamen z.B. mit dem Pluginnamen als Präfix versehen. So hat das Plugin kein Zugriff auf deine eigenen Tabellen.

Ganz genau. Das Problem dabei ist, das Plugin benutzt ja dann evtl. Objekte die dem DB-Interface und dem jeweiligen Service noch nicht bekannt sind. Das müsste ich dann mit einem generischen Typen lösen. So ähnlich wie hier: How can I use a generic type with entity framework core? Das teste ich mal mit LiteDB ähnlich wie bei Abts Projekt Data.LiteDBRepository

// Nachtrag:
Es ging doch einfacher als gedacht. Falls jemand mal was ähnliches braucht:


// Interface:
        Task AddPluginData<T>(string PluginIdentifier, T data);

        Task<List<T>> GetPluginData<T>(string PluginIdentifier);

// Implementierung mit LiteDB
        public Task AddPluginData<T>(string PluginIdentifier, T data)
        {
            return Task.Run(() =>
            {
                // Collection holen:
                var col = _db.GetCollection<T>($"Plugin_{PluginIdentifier}");
                col.Insert(data);
            });
        }

        public Task<List<T>> GetPluginData<T>(string PluginIdentifier)
        {
            return Task<List<T>>.Run(() =>
            {
                // Collection holen:
                var col = _db.GetCollection<T>($"Plugin_{PluginIdentifier}");
                return col.Query().ToList();
            });
        }

// Aufruf 

           await av.AddPluginData<Person>("MY_PLUGIN",
                new Person()
                {
                    Name = "Max Mustermann",
                    Age = 32
                }
                );


            await av.AddPluginData<Person>("MY_PLUGIN",
                new Person()
                {
                    Name = "Hans Dampf",
                    Age = 39
                }
                );


            foreach(var person in await av.GetPluginData<Person>("MY_PLUGIN"))
            {
                Console.WriteLine($"{person.Name} {person.Age}");
            }

        public class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }


Kann man natürlich noch ausbauen (CRUD). Die Frage ist es ob es mit einem SQL-Server auch so einfach geht 😁

Danke jedenfalls für eure Tipps!

30.10.2020 - 11:42 Uhr

Die Pluginfähigkeit ist nicht das Problem, das Datenbankdesign ist das Problem. Also dass ich im Interface auch Datenoperationen ausführen kann die ich nicht kenne. Was ich mir auch gedacht habe, in der oberen Tabelle einen JSON-String als Value zu speichern. Das wäre wahrscheinlich nicht gerade effizent, würde aber funktionieren 😁

30.10.2020 - 09:41 Uhr

Hi,

ich habe ein lokales Programm mit dem auf eine Datenquelle (z.B. SQLite-Datenbank) zugreifen kann.
Den Datenzugriff gestalte ich über ein Interface (GetOrders(), AddOrder(),...) damit ich die Datenquelle wechseln kann.

Nun möchte ich gerne dass man Module dynamisch hinzufügen kann. Also eine Art Pluginsystem.

Wie designe ich das jetzt am besten, sodass die Module auch Datenbank Zugriff haben und selbst Daten schreiben und auslesen können?

Ich habe mir schon überlegt dass ich in der Datenbank eine Tabelle anlege für alle Module die dann z.B. so aussieht:

| Module-Name/ID | Key | Value |

Also dass jedem Modul ein Key-Value-Paar zur Verfügung steht. Damit könnte ich auch im bisherigen Interface/Service eine generische Funktion hinzufügen (GetModuleKeyValue(moduleID, key), SetModuleKeyValue(...)). Das wird wahrscheinlich sehr unsauber, da ja mit dem Schlüssel ziemlich viel Information beschrieben werden muss (z.B. "Order-23-LieferantenApiUrl",...)

Hat da jemand noch einen Tipp für mich oder bessere Lösungsvorschläge?

29.10.2020 - 10:23 Uhr

Auch keine schlechte Idee leider ist der fehler mit den falschen früchten immer noch.

Da würdest du oder wir zumindest den Fehler auf den ersten Blick erkennen, und nicht wie bei diesem Wirrwarr 😉

29.10.2020 - 08:54 Uhr

Vielleicht würde es dir einfacher fallen das ganze in eine eigene Klasse auszulagern.

Pseudo-Beispiel:



public class Machine(){

 public bool RowTopWin{...} // gibt zurück ob 1. Zeile Gewinn
 public bool RowMiddleWin{...}
 public bool ColumnLeftWin{...}

}


28.10.2020 - 10:22 Uhr

Du hast recht, das ist mir gar nicht aufgefallen. Ich habe jetzt eine Update Methode dafür geschrieben. Damit geht es jetzt. Danke!

27.10.2020 - 18:03 Uhr

Ich glaube ich habe mein Problem nicht deutlich genug erläutert.

Als Beispiel habe ich ein Objekt der ViewModel-Liste gebunden, und zeig in einer TextBox ein Feld davon. Wenn ich zwischenzeitlich die Objekte neu lade und danach die TextBox änder, konnte ich in der Liste die Änderung nicht mehr nachverfolgen, da ja die Referenz verloren ging (durch Clear).
Mit dem Code geht es jetzt. Also die "Referenz" ist scheinbar die selbe, sie wurde nur ersetzt.

27.10.2020 - 16:59 Uhr

Hi,

danke für eure Tipps,

habe es mir jetzt doch nochmal etwas umgeschrieben, das funktioniert soweit jetzt. Falls jemand es brauchen sollte:


            // Modelle von Datenbank beziehen:
            var orders = _SqlRepo.GetOrders();
            orders.Wait();


            // Modelle die in ViewModel Liste bereits referenziert sind:
            var ordersToReplace = _Orders.Where(
                c => 
                orders.Result.FirstOrDefault(old => old.OrderID == c.OrderID) != null)
                .ToList();
            
            
            // vorhandene ViewModels ersetzen:
            ordersToReplace.Select(
                c => 
                c = new OrderViewModel(
                    orders.Result.Where(c => c.OrderID == c.OrderID).First()
                    )
                );

            // ViewModels, für die es kein Modell gibt ==> löschen
            var ordersToDelete = _Orders.Where(
                vm => 
                orders.Result.FirstOrDefault(model => model.OrderID == vm.OrderID) == null)
                .ToList();

            foreach(var orderToDelte in ordersToDelete)
                _Orders.Remove(orderToDelte);


            // Models, für die es kein ViewModel gibt ==> hinzufügen:
            var ordersToAdd = orders.Result.Where(
                c => _Orders.FirstOrDefault(vm => vm.OrderID == c.OrderID) == null)
                .ToList();

            // ViewModel für Modell erstellen & hinzufügen:
            foreach (var order in ordersToAdd)
                _Orders.Add(new OrderViewModel(order));

26.10.2020 - 17:42 Uhr

Ich verstehe zwar nicht genau was du vor hast, am einfachsten ist aber wahrscheinlich wenn du das Bild im Form3-Konstruktor übergibst:

Form3 form3 = new Form3("C:\mein_bild.jpg");

bzw. siehe hier: [FAQ] Kommunikation von 2 Forms

24.10.2020 - 20:23 Uhr

Hey noch eine weiterführende Frage:

Ich arbeite in meiner Datenbank mit "Order"-Objekten, diese mappe ich mir in "OrderViewModels" für WPF,...

Speichere ich z.B. ein Objekt ab, lese ich danach wieder die Datenbank aus.


            // "Order"-Objekte aus der Datenbank
            var orders = await _SqlRepo.GetOrders();
            // Liste mit ViewModels (werden in Window abgerufen)
            _Orders.Clear();
            
            foreach(var order in orders)
            {
                var vm = new OrderViewModel(order);

                _Orders.Add(vm);
            }

Durch das Clearen gehen ja jedesmal die Referenzen verloren, wenn z.B. ein Fenster mit Details das jeweilige OrderViewModel noch verwendet. Das funktioniert zwar, ich kann Änderungen dann aber nur noch an einer Stelle tracken.

Gibt es ein fertiges Pattern mit dem ich erst die bestehenden ersetze (z.B. anhand OrderID identifiziere), dann nicht mehr vorhandene (gelöschte) entferne und neu hinzugefügte, neu erstelle?
Das kann man natürlich alles von Hand machen, ich schätze das Problem ist aber sicher schon öfter vorgekommen, ich weiß nur nicht nach was ich suchen soll.

24.10.2020 - 11:43 Uhr

Zudem schreibt man in Unity ja auch eher Scripts statt vollwertige Programme.
Bei mir ist es so das ich mit 24 gerne noch eine Ausbildung als Anwendungsentwickler starten möchte.
Da ich leider nur einen Hauptschulabschluss (und diesen auch nicht gut) möchte ich mein Wissen über C# ausbauen. ...
Allerdings ist es ja auch so das Enterprise C# Entwicklung eine völlig andere ist als Unity Entwicklung.

Also ich will dir nicht den Mut nehmen, aber bei größeren Firmen, die z.B. Enterprise Software im B2B entwickeln, zählt ehr größere Erfahrung oder coole Projekte zum vorzeigen (GitHub Profil,...) wenn kein Studium vorhanden ist. Bei einem kleinen Betrieb der für interne Zwecke entwickelt mag das keine Rolle spielen. Aus eigener Erfahrung kann ich aber sagen dass so eine Ausbildung nicht gerade ein Qualitätsmerkmal ist, Erfahrung ist da viel wichtiger.

Bzgl. dem Lernen, ich rate dir wirklich ein umfangreicheres Buch an die Hand zu nehmen, in dem möglichst viel behandelt wird. Wenn du das mit Tutorials oder YouTube-Videos lernen willst verschwendest du eigentlich nur Zeit, da du irgendwann merkst dass Grundlagen fehlen. Ich habe zumindest noch keine online-Videoreihe gesehen die den Umfang und Qualität von z.B. "C# 8 mit Visual Studio 2019" hat.

23.10.2020 - 11:53 Uhr

Der dort erwähnte ViewManager entspricht dabei dem WindowsService, den MrSparkle nannte.

Danke für den Tipp!


    public interface IWindowManager
    {
        void ShowOrderWindow(OrderViewModel order);
...
    }

So habe ich es jetzt gemacht, das MainViewModel initalisiert den WindowManager, und nutzt den Manager dann um die Fenster aufzurufen.
Dann ist der Manager ein Ausbruch aus dem Pattern. Aber ich denke noch ein recht übersichtlicher 👍

Danke euch!

22.10.2020 - 08:47 Uhr

Nochmal dazu eine Frage:

Bisher habe ich es so gemacht:
im MainWindowViewModel habe ich einen Command der ein neues Fenster öffnet, dem das zugehörige ViewModel zuweist und den DbService mitgibt.

Jetzt sollte die UI Schicht ja eigentlich von den ViewModels komplett getrennt sein. Also das MainWindoViewModel das zweite Fenster gar nicht kennt.

Wie mache ich das am besten, dass ich das in XAML definiere? Also einen Command der ein neues Fenster öffnet, ViewModel mitgibt. Brauche ich für sowas dann doch Codebehind?

19.10.2020 - 16:30 Uhr

Meiner Meinung hängt der langfristige Erfolg ehr von Azure und dessen Entwicklung ab.

Was ich noch erstaunlich häufig in Unternehmen sehe: Programme die mit Visual Basic 6 oder Visual C++ 6,... entwickelt wurden und noch regelmäßig gepflegt werden! Also ich denke C# bzw. .NET bleibt uns auch noch eine Zeit lang 😁

19.10.2020 - 07:43 Uhr

Du hast eine Liste mit Mails, da weißt du die Anzahl.
Anstatt die zusammen in die Methode zu geben, kannst du sie ja einzeln abarbeiten und den Status aktualisieren.

Funktionieren deine Methoden wirklich?! Du gibst ja nicht mal einen Task zurück. Da macht der Aufruf dann halt auch keinen Sinn.


await System.Threading.Tasks.Task.Run(() => PrepareMailsAsync(emailMessages));

18.10.2020 - 12:23 Uhr

Nur mal interessehalber, was wird das für ein Projekt? Ich verstehe nicht ganz wieso man Nutzer Adminrechte gibt aber sowas dann so stark kontrollieren will. Hört sich ehr nach so einem Schul-PC Schutzprogramm oder Mitarbeiterüberwachung an 😄

11.10.2020 - 18:06 Uhr

Klappt zu meiner Überraschung nicht. Was mache ich denn falsch?

Übersicht über die .NET Core-CLI

Gleich im ersten Absatz, Installieren von .NET Core SDK. Kannst du aber auch mit dem VS Installer.

11.10.2020 - 15:56 Uhr
<Button Content="Hallo Mitarbeiter"   
  	Command="{Binding Path=SelectedEmployee.HelloCommand}"   
  	Margin="5,0,0,0"  
  	Background="LightYellow" />  

Prinzipiell funktioniert das schon, wenn ein Mitarbeiter ausgewählt ist.
Wenn jedoch kein Mitarbeiter ausgewählt ist, wird der Button nicht ausgegraut, was nicht sonderlich schön ist.

Woher soll der Button das auch wissen? Dafür kannst du es ja an die **IsEnabled **Eigenschaft binden.

09.10.2020 - 16:54 Uhr

Hi,

nur ganz kurz eine Frage, ich weiß das wurde schon mehrfach durchgekaut, ich bin mir aber nicht sicher was "sauberer" ist:

Aus dem MainWindowViewModel rufe ich per Command ein zweites Fenster auf (OrderDetails), welches ein OrderDetailsViewModel als Context hat. Dem übergebe ich im Konstruktor das gewählte Order Objekt und das DB-Repository.


        public OrderDetailsViewModel(Order order, IDBRepo dbRepo)

Beim Speichern-Command im OrderDetailsViewModel will ich eine Aktualisierung im MainWindowViewModel anstoßen.

Mir fallen jetzt zwei Möglichkeiten ein:


public OrderDetailsViewModel(Order order, IDBRepo dbRepo, MainWindowViewModel parent)

==> ich übergebe die Referenz des Parents im Konstruktor und rufe dann eine Methode auf (z.B. refreshOrders,...)

Oder ich abonniere im MainWindowViewModel ein Event des OrderDetailsViewModels (z.B. DetailsSaved,...)

Was ist besser? Bzw. habt ihr einen besseren Vorschlag?
Danke!

09.10.2020 - 14:07 Uhr

Gibt dafür auch nicht wenige fertige Systeme, falls man das Rad nicht neu erfinden möchte. z.B.: nUpdate - .NET Update Solution

07.10.2020 - 18:44 Uhr

Nur mal als kleines Praxisbeispiel:

Ich habe es mittlerweile bei vier DAX Unternehmen gesehen, dass auch dort das Thema auf dem Tisch liegt. Da wird es von den Mitarbeitern zwar auch nur belächelt, langfristig aber übernommen. Aber nur um mögliche Konsequenzen zu vermeiden und das Thema schnell wieder vergessen zu können.

30.09.2020 - 20:35 Uhr

Problem es gibt keine einfache Beschreibung was der Unterschied zwischen Parallel und Asynchron ist.

Ohne solche Sätze wie:
Parallele Verarbeitung vs. Order Preservation sind gegensätzliche Anforderungen.
Das Einhalten einer Order ist extrem kostenintensiv; daher gibt es weder in PLINQ noch in der TPL entsprechende Funktionalitäten

Asynchron --> man macht weiter ohne zu warten
Parallel --> es läuft zur selben Zeit ab

Bei deinem Fall macht das parallele arbeiten absolut keinen Sinn, das könntest du z.B. machen wenn du Arrays mit Pixeln hast und die mittels Interpolation skalieren willst. --> hohe Rechenpower notwendig, kann nebeneinander laufen, nicht abhängig,...
Bei einer Datenbankabfrage macht es halt gar keinen Sinn, das wird auch nicht schneller. Und du lastest damit deine CPU-Kerne auch nicht aus 😁 Alles wie oben schon mehrfach erwähnt.

Bei dir bietet es sich an asynchron zu machen, dass die GUI oder was auch immer nicht hängen bleibt. Was jetzt genau dein Problem damit ist, verstehe ich aber immer noch nicht.

29.09.2020 - 11:06 Uhr

Man könnte sich auch mal
>
anschauen.

Da wird aber auch nicht die richtige Reihenfolge garantiert, und es lohnt sich glaub an erst ab sehr hohen Anzahlen.

Warum wartest du nicht einfach mit await? Warum muss das parallel ablaufen? Vorallem bei den selben Datenbankzugriffen. Oder am Besten mehrere auf einmal wie T-Virus sagt.

22.09.2020 - 09:52 Uhr

Ist zwar auch nicht optimal, aber die einzige Lösung die mir einfällt OnTheFly die Zugangsdaten der Datenbankserver ändern zu können ohne die Application an sich zu updaten.

Ich wollte nur sagen, dass ich das Abrufen von Credentials über eine HTTP Schnittstelle schöner finde als das zusätzliche Verbinden auf eine Datenbank. Dabei ist man auch nicht nur auf Microsoft angewiesen (Open-Source gibt es ja auch)...
Mir kommt das irgendwie sehr bekannt vor, wenn z.B. irgend ein Leiter nur die Technologie nutzen will mit der er auch vertraut ist obwohl es bessere Alternativen gibt (auch bei DAX Unternehmen) 😁
Wie gesagt, ist nur meine eigene Meinung. Ich denke die Diskussion hilft dir auch nicht weiter, darum sollten wir es jetzt dabei belassen.

21.09.2020 - 18:52 Uhr

Also da finde ich es schon schöner, wenn man so einen Zugriff hat, anstelle dass jeder Client auf irgendeine Datenbank connected. Naja das muss dann halt jeder selber wissen 😁