Laden...

Forenbeiträge von Palladin007 Ingesamt 2.080 Beiträge

27.07.2023 - 11:31 Uhr

NICHT im Konstruktor 😉 Ist generell eine blöde Idee.

Am besten ist es, Du lädst aus der UI gesteuert die Daten, also z.B. durch einen Button-Klick (Command).
Du kannst es aber auch in einem UI-Event das ViewModel über den DataContext suchen und dort die LoadDataAsync-Methode aufrufen, das wäre auch noch MVVM konform.
Ich hatte das früher ganz gerne durch meine selbst gebaute Navigation gelöst, das ViewModel wird informiert, wenn es angezeigt wird und lädt dann die Daten. Der Aufbau verlangt aber eine gewisse Infrastruktur.

23.07.2023 - 20:02 Uhr

mutable = änderbar

Ändere das Entry-Objekt und ersetze es nicht mit einem Neuen.
KANN besser sein, muss aber nicht, hängt von deinem Problem ab.

public int Number { get; } // immutable
public int Number { get; set; } // mutable
23.07.2023 - 14:48 Uhr

Nein, keine Abkürzung.
Du könntest aber für den Getter eine Lambda-Expression nutzen:

public NoTradeDay Monday
{
    get => _monday;
    set
    {
    	_monday = value;
    	RecalculateValues();
    }
}

Vielleicht ändert sich das aber in Zukunft noch, es ist ein Semi-Auto-Properties-Feature in der Entwicklung.

Das soll (soweit ich weiß) etwa so aussehen:

public int A
{
    get;
    set => field = value + 1;
}

"field" ist dabei ein Keyword und repräsentiert die Variable.

Wie der konkrete Stand ist, weiß ich aber nicht, offiziell bei Microsoft auf der Seite steht noch nichts.

23.07.2023 - 08:57 Uhr

@Th69: Im Debugger bleibt die Anwendung ja nie hängen - zumindest habe ich das so verstanden.

Und als externe Anwendung kannst du per "Attach to Process" die Anwendung nachträglich debuggen

Das ist aber ein guter Punkt.

Du müsstest die Anwendung  als Debug-Version bauen und damit den Fehler reproduzieren.
Wenn die Anwendung dann hängt, kannst Du ggf. Visual Studio an den Prozess attachen und so herausfinden, welche Threads/Tasks wo hängen.

22.07.2023 - 20:17 Uhr
var index = HorizontalLinesTillTouch.IndexOf(Entry);

HorizontalLinesTillTouch[index] = Entry2;

Oder Du machst die Entries mutable, kann unter Umständen besser sein.

22.07.2023 - 15:36 Uhr

Das klingt nach Multithreading-Chaos, passt auch dazu, dass es beim Debuggen immer läuft.

Dass die Form nicht geschlossen werden kann, würde ich so erklären, dass der UI-Thread in einem Deadlock fest hängt, dann hilft nur noch Thread oder Prozess killen.
Und wo er stehen bleibt, wirst Du ohne Debugger nur mit entsprechendem Logging feststellen können.

22.07.2023 - 15:11 Uhr

Wieder ein Fall von: Ohne MVVM machst Du es dir unnötig schwer.

https://mycsharp.de/forum/threads/118261/artikel-mvvm-und-databinding

Nimm eine ObservableCollection, wirf da deine Objekte rein und binde sie als ItemsSource.
Dazu ein Command, den Du an den Button bindest und als CommandParameter bindest Du den aktuellen DataContext ("{Binding}").

In der Methode zum Command kannst Du dann einfach den Parameter casten, aus der ObservableCollection entfernen und der Rest passiert automatisch.
Ist auch eine Ecke weniger Code.

17.07.2023 - 20:33 Uhr

Meine Glaskugel ist leider kaputt.

Finde raus, wo er sich auf hängt, der Debugger hilft dabei: [Artikel] Debugger: Wie verwende ich den von Visual Studio?

Mit etwas Code können wir dann auch weiterhelfen.

13.07.2023 - 11:44 Uhr

Wenn Du DevExpress brauchst, würde ich da mit der Recherche beginnen - für was bieten die ihre Frameworks denn überhaupt an? Für WPF gibt's meiner Erfahrung nach recht viel und WPF wird denke ich auch nicht so schnell eingestampft, dafür ist das zu verbreitet.


Und ja, MAUI ist in gewisser Weise eine Neuauflage von Xamarin.
MAUI arbeitet aber in einigen Punkten anders als Xamarin, insbesondere die Art und Weise, wie die verschiedenen Plattformen verwaltet werden.


Und ich persönlich finde Blazor hervorragend, meine Firma setzt auch voll auf Blazor und ist bisher zufrieden.
Es ist aber immer noch eine recht neue Technologie, das darfst Du nicht vergessen.

Insofern halte ich deinen Plan, Blazor als "Haupt"-Technologie in Zusammenarbeit mit MAUI zu verwenden, für durchaus sinnvoll. Allerdings gibt es meines Wissens nach aktuell neben MAUI keine andere Desktop-Technologie, die mit Blazor arbeiten kann, vielleicht ändert sich das aber noch.

Für ein privates Projekt habe ich mich auch für MAUI + Blazor entschieden, aus dem Grund, dass es hoffentlich bald eine Linux-Variante für MAUI oder ein Linux fähiges Desktop-Framework gibt, das mit Blazor arbeiten kann. Bis dahin läuft mein Projekt eben nur auf Windows.
Das Projekt ist aber noch so frisch, dass ich nichts konkretes dazu sagen, nur, dass ich den Plan prinzipiell gut finde.

11.07.2023 - 16:27 Uhr

Zitat von Dolce

Ich habe das Privileg, ein neues, größeres Desktop-Projekt erstellen zu dürfen.

Soll das Projekt denn nur auf Windows laufen?

Dann würde ich auch WPF in die Betrachtung mit einbeziehen.
Das ist zwar alt und das merkt man auch an vielen Stellen, aber es ist immer noch ein mMn. hervorragend gutes Framework mit sehr umfangreichen Frameworks (z.B. MahApps) und vielen Leuten in der Community, die sich gut damit auskennen. Außerdem hat es MVVM quasi "erfunden", andere Frameworks führen es nur fort, Du bist konzeptionell also nicht so weit entfernt vom aktuellen Stand der Technik.
Aber Du bist natürlich an Windows gebunden.

Ich habe selber vor zwei Jahren ein WPF-Projekt umgesetzt, das einzige, was ich vermisst und daher selber nachgerüstet habe, ist das Hosting-Konzept von ASP.NET. Später habe ich dann ein Framework gesehen, was das auch macht, selber genutzt habe ich es aber noch nicht: Wpf.Extensions.Hosting
MAUI nutzt das gleiche Konzept, daher denke ich, dass das ein prinzipiell guter Weg ist.

Wenn es auch auf Linux laufen soll, hast Du von Microsoft meines Wissens nach sowieso keine wirkliche Option. WinUI ist Windows only, MAUI gibt's aktuell (noch) nicht für Linux und WPF ist sowieso Windows only. Du kannst eine Website entwickeln und einen Wrapper, der sie hostet und einen Client mit Browser-Control startet. Oder Du greifst auf Community-Projekte wie Avalonia zurück, das läuft auf Linux.


Zu MAUI und WinUI kann ich leider nicht viel sagen.
Mit MAUI habe ich bisher nur experimentiert, mir gefallen viele Dinge und ich würde gerne mal ein größeres Projekt damit umsetzen, aber ob das wirklich schon dafür geeignet ist, weiß ich nicht.
Und mit WinUI habe ich noch gar nichts gemacht.


Zitat von Abt

Auf der anderen Seite höre ich, dass es ein enorm zufriedenes Ökosystem rund um Avalonia gibt.

Dem kann ich mich aber nicht anschließen.
Avalonia sieht auf den ersten Blick wie WPF aus (was ja auch gewollt ist), auf den zweiten und dritten Blick hatte ich bei meinem letzten Avalonia-Projekt viele Probleme. Ich weiß nicht, ob das meine Fehler waren, oder wirklich Design-Fehler. Z.B. ist das Styling-Konzept mMn. nicht zuende gedacht und viel zu flexibel (nicht unflexibel), das hatte WPF mMn. deutlich besser gelöst.

10.07.2023 - 17:04 Uhr

Der Enum-Datentyp kann sowohl einen einzelnen Wert, als auch mehrere Flags darstellen. Technisch ist es am Ende nur ein long, aber der Compiler muss wissen, wie er mit den Werten umgehen soll, wenn Du long und das Enum zusammen nutzen möchtest, weiß der Compiler nicht mehr, von welchem Typ er die Operatoren nun nutzen soll.

By the way, als Tipp:

[Flags]
enum MyEnum : long
{
    None = 0,
    A = 1 << 0, // 1
    B = 1 << 1, // 2
    C = 1 << 2, // 4
    D = 1 << 3, // 8
}

So ist das bedeutend übersichtlicher.
Du kannst auch die Bit Flags direkt schreiben:

[Flags]
enum MyEnum : long
{
    None = 0,
    A = 0b0000_0000_0000_0001, // 1
    B = 0b0000_0000_0000_0010, // 2
    C = 0b0000_0000_0000_0100, // 4
    D = 0b0000_0000_0000_1000, // 8
}

Ich persönlich würde das aber nur nutzen, wenn Du z.B. technisch bestimmte Bit-Flags vorgegeben hast und die nicht mit einem einfachen left-shift "gezählt" werden können, wie im oberen Beispiel.

Zitat von Abt

0 als Value ist immer schlecht/ungünstig - außer es soll eben "Nichts" ausdrücken.

Das stimmt natürlich - daher auch immer nur "None", weil es "Nichts" ausdrücken soll.
Außerdem gibt es den 0-Fall immer gibt, ganz egal, was ich tue. Mit "None" gebe ich dem einen Namen, der als falsch erkennbar ist.

10.07.2023 - 13:33 Uhr

Ich verwende für sowas gerne einen None-Eintrag mit 0, aus dem einfachen Grund, dass es der Default-Wert ist. Und man braucht kein zusätzliches Nullable, der Typerzeugt von sich aus kein potentiell ungewolltes Verhalten.

10.07.2023 - 13:12 Uhr

In deinem Eingangs-Beispiel mischst Du Enum und Long:

long MyFlags = StdVerzListenFlag.MYDOCUMENTS & StdVerzListenFlag.MYMYMUSIC; // Long

if((MyFlags & StdVerzListenFlag.DESKTOP) == StdVerzListenFlag.DESKTOP) // Enum

Teste mal nur mit dem Enum:

StdVerzListenFlag MyFlags = StdVerzListenFlag.MYDOCUMENTS & StdVerzListenFlag.MYMYMUSIC; // Enum

if((MyFlags & StdVerzListenFlag.DESKTOP) == StdVerzListenFlag.DESKTOP) // Enum
08.07.2023 - 20:37 Uhr

Eher so:

ConsoleApp2.exe --id 1 --value1 a1 --value2 b1 --id 2 --value1 a2 --value2 b2

Da kommen drann 1 = a1, b1 und 2 = a2, b2 raus.
Die ID mehrfach vergeben möchte ich eigentlich nicht.

Vielleicht sollte ich doch eine Config-Datei bauen, das hätte auch andere Vorteile und wäre sehr viel flexibler.

Das Optimum wäre ja, ich könnte die ganzen Daten aus der csproj lesen (da hab ich die Daten für einen Analyser auch, über ein Item mit Metdaten), aber MSBuild Projekt-Dateien lesen scheint ziemlich komplex.

08.07.2023 - 17:32 Uhr

Danke für den Vorschlag, aber das funktioniert in meinem Fall leider nicht.

Eigentlich habe ich zwei Werte, die einer ID zugeordnet werden sollen, es müssen aber nicht beide Werte angegeben werden, die Anzahl ist also variabel.
Ich hatte es eingangs nicht geschrieben, weil ich das Beispiel einfach halten wollte und nicht an diesen Weg gedacht habe - sorry ^^

Oder übersehe ich etwas?

08.07.2023 - 15:53 Uhr

Guten Nachmittag,

ich suche einen Command line parser, der aufeinander folgende Werte gruppieren kann.

Als Beispiel:

--foo x --id 1 --value a --bar true --id 2 --bla y --value b

Das Beispiel soll dann "1a" und "2b" in einer Liste sammeln.
Dass zwischen den Werten auch was Anderes (der "--bla" Wert) stehen kann, ist nice to habe, aber nicht notwendig.

Ideal wäre, wenn das mit System.CommandLine geht, weil darauf meine bisherige Lösung basiert.
Andere Frameworks gehen aber auch, ist dann nur mehr Arbeit für mich.

Kennt jemand ein Framework, was sowas bietet?

Besten Dank

28.06.2023 - 10:43 Uhr

Es gibt ein Thema für Bugreports: https://mycsharp.de/forum/threads/123661/sammelthema-wuensche-und-bugreports-mycsharp

Und das Thema hatte ich anfangs auch schon reportet, Abt kam wohl leider noch nicht dazu.
Ich kann dir als Workaround aber den DarkReader, der baut dir ein ganz anständiges Dark-Theme, mit dem man auch schreiben kann.

22.06.2023 - 14:48 Uhr

Erste Hälfte deines Beitrags:

Danke für die Richtungstellung.
Dass Sharplab so arbeitet, wusste ich nicht und dass es da tatsächlich einen Unterschied gibt, auch nicht.
Wieder was gelernt

Zweite Hälfte:

nicht richtig einordnen. Vllt. ist es richtig gemeint od. auch nicht. Jedenfalls so wie ich es beschrieben haben ist es im Sinne von Nullable-Annotations.

Ich glaube, ich meine das, was du beschrieben hast.
Worauf ich anspiele (in den Klammern), ist die Option, die warnungen als Fehler zu behandeln.
In dem Fall zwingt mich der Compiler (oder Visual Studio, egal) dazu, das null richtig zu behandeln.

Das hat eigentlich noch nie wirklich Sinn gemacht (also Null-Checks in nicht öffentlichen Methoden), da diese ja nur von public Methoden aufgerufen werden können (direkt od. indirekt).

... und die wiederum prüfen allles sorgfältig, bevor es weiter geht.

Ich meine mit "internal" aber eher, ob das ganze Projekt oder der Teil davon dafür gedacht ist, extern weiterverwendet zu werden, also z.B. bei einem Framework. Wenn nur ich (oder mein Team) daran arbeitet und die Nullable Reference Types richtig verwendet, gibt's auch kaum NullReferenceExceptions. Es kann natürlich sein, dass man irgendwas nutzt, was das nicht unterstützt (z.b. WPF), aber dann muss er erste Aufrufer dafür sorge tragen, dass das nicht null ist, was da weiter gegeben wird.

22.06.2023 - 10:31 Uhr

Guckst Du hier:

https://sharplab.io/#v2:EYLgtghglgdgPgAQEwEYCwAoTCDMACZPAYUwG9M9K8AHAJygDcIAXAUwIBY8AVVgZ2YoAFAHtgAK1YBjZngAeASgpVyGKurxQAZniFy8AQgC8eGAFcANhaVqNlVXbsIUATiEAiABKsrIvAHURWgsAE3cFAG5lOwBfaLw420p4ukYWdgQuXgEkUQlpWUV4h0dtXX0jE3MrG0c8ErrKBAB2KKSNRLr49Wc3Lx8LP0DgsMj4xJigA==

Das Ding zeigt dir, was der Compiler beim Lowering-Schritt macht und siehe da: Es ist technisch identisch 😉
Mach es von der Übersichtlichkeit abhängig, wähle je Situation das, was am übersichtlichsten ist.

Einen (mMn.) Best Practices gibt's aber: Nullable Reference Types
Im private oder internal Code schreibe ich persönlich gar keine Null-Checks mehr, außer ich markiere den Parameter als nullable, dann zwingt (wenn ich es als Fehler behandeln lasse) der Compiler mich dazu.

19.06.2023 - 07:41 Uhr

Was spricht gegen die Win32-Lib?
Für MVVM braucht man einen kleinen Wrapper, aber das ist ja nicht so kompliziert.
Eine WPF-Implementierung ist mir nicht bekannt, aber die würde auch nur das gleiche machen, wie die Win32-Lib.

16.06.2023 - 13:43 Uhr

Bedingte Kompilierung würde ich nach Möglichkeit so lange nicht nutzen, wie Du es nicht zwingend brauchst.

Ein Beispiel, wo ich es mal verwendet habe, war ein Feature-Switch. Es sollte zwei Versionen geben, Version 2 kostet mehr, und erlaubte mehr Funktionen, die Code-Basis ist aber die gleiche. Einerseits gab's im Code eine Unterscheidung, welches Feature zugelassen ist, aber damit der Anwender sich die Features nicht mit über diverse Tricks doch aktivieren kann, habe ich den entsprechenden Code ganz einfach komplett entfernt. So würde der Anwender, wenn er das Feature doch aktivieren könnte, trotzdem kein funktionsfähiges Feature erhalten, da es nicht implementiert ist.
Dafür habe ich dann in Visual Studio zwei Konfigurationen für Debug/Release und Feature on/off erstellt, je Konfiguration ein Symbol definiert (geht in der Projekt-Datei mit <DefineConstants>) und im Code mit #if MyConstantden Code dann mit kompilieren lassen, oder nicht.

Du hast aber zwei Varianten, die parallel vorhanden und auch nutzbar sein sollen, da wäre sowas also denkbar schlecht geeignet.
Du kannst z.B. eine Basis-Klasse mit gemeinsamen Code und ein bis zwei Ableitungen für die jeweiligen Varianten erstellen.
Oder Du arbeitest mit dem Strategy Pattern, womit Du das Verhalten "von außen" hinein geben und so verändern kannst.
Oder Du belässt alles in einer Klasse und bietest Properties, die einzelne Funktion ein- bzw. ausschalten können.
Für einen komplexen Text-Editor würde ich mit Vererbung arbeiten (CodeViewBase, CodeView, CodeEditor), oder alles zusammen + Properties zum Einstellen, je nachdem, wie einfach oder kompliziert die jeweilige Variante wird. Oder Du teilst es in separat genutzte Komponenten auf, wie gut sich das in diesem Beispiel umsetzen lässt, müsstest Du dann schauen.

16.06.2023 - 13:28 Uhr

Beim schreiben habe ich auch das Problem, dass ich beim drücken von Enter immer eine zusätzlich Leerzeile habe.

Das habe ich bei anderen MD-Editoren auch schon gesehen und Word macht das auch so.

Du kannst das in allen diesen Programmen (bzw. die, die ich kenne) so umgehen, dass Du beim Enter drücken zusätzlich Shift gedrückt hältst.
Ich habe mich da auch längst dran gewöhnt und finde es sogar gut so.

16.06.2023 - 10:45 Uhr

Nochmal zurück zum Dotfuscator:

Was hast Du alles public und internal?
Ein Obfuscator kann natürlich nur das verändern, worüber er auch die volle Kontrolle hat.
Alles, was von außen erreichbar bleiben muss (z.B. public oder protected in public class) muss auch genau so erreichbar bleiben, wie Du es bei der Arbeit vorgesehen hast, entsprechend wird der Obfuscator nichts daran ändern.

Wenn Du also alles public hast, dann wird auch nichts an diesen Membern geändert.

16.06.2023 - 10:27 Uhr

Du kannst natürlich jederzeit einen Server ins Internet stellen, der DLLs zum Download anbietet und deine Anwendung lädt sie herunter und lädt sie in die AppDomain.
Das geht, aber bringt dir auch nichts, denn wenn Du die DLL als Datei speicherst (was nicht notwendig aber sinnvoll ist, wenn sie nicht jedes Mal geladen werden soll), kann man sie genauso wieder dekompilieren. Und wenn sie nicht als Datei irgendwo liegt, gibt's immer noch einen Web-Server, der sie als Datei anbietet, man kann sie sich also einfach ziehen und dekompilieren. Ein Passwort-Schutz bringt auch nichts, denn deine Anwendung muss das Passwort ja kennen, dann dekompiliert man die lokal vorhandene Anwendung, sucht das Passwort und lädt sich die DLLs vom Server und so weiter.

Wie Abt schon angedeutet hat:
Es gibt keinen effektiven Schutz, es ist einfach nicht möglich, den Code 100% zu schützen.
Nicht mal mit C++ oder Native AOT geht das, es ist allerdings bedeutend schwieriger, noch nutzbare Informationen herauszuziehen.

15.06.2023 - 18:45 Uhr
public delegate void SetTransponderIdAction(long transponderID);
public event SetTransponderIdAction SetTransponderId;

public void Test()
{
    SetTransponderId += cConnector_SetTransponderId;
    SetTransponderId?.Invoke(1);
}

... oder ...

public event Action<long> SetTransponderId;

public void Test()
{
    SetTransponderId += cConnector_SetTransponderId;
    SetTransponderId?.Invoke(1);
}
    
public void cConnector_SetTransponderId(long obj)
{
    // ...
}

... oder ...

public event EventHandler<long> SetTransponderId;

public void Test()
{
    SetTransponderId += cConnector_SetTransponderId;
    SetTransponderId?.Invoke(this, 1);
}
    
public void cConnector_SetTransponderId(object sender, long e)
{
    // ...
}

... oder ...

public class SetTransponderIdEventArgs : EventArgs
{
    public long TransponderID { get; }
    
    public SetTransponderId(long transponderID)
        => TransponderID = transponderID;
}

public event EventHandler<SetTransponderIdEventArgs> SetTransponderId;

public void Test()
{
    SetTransponderId += cConnector_SetTransponderId;
    SetTransponderId?.Invoke(this, new SetTransponderIdEventArgs(1));
}
    
public void cConnector_SetTransponderId(object sender, SetTransponderIdEventArgs e)
{
    // ...
}

Such's dir aus.
Sieht aber generell nach einem Fehl-Design aus, so weitreichende Event-Steuerung führt meiner Erfahrung nach immer zu Problemen.

14.06.2023 - 09:00 Uhr

MAUI ist etwas völlig anderes, als eine "normale .NET Framework Applikation". Was soll das überhaupt sein, WinForms, oder WPF?
MAUI löst viele Dinge sehr anders und liefert eigene Styles mit, da kann es durchaus sein, dass Standard-Farben abweichend definiert sind.

Und es gibt verschiedene Grautöne, probiere die doch mal durch, ggf. sagt dir ein anderer Grauton mehr zu.
Und deine Farbe RGB(192, 225, 225) ist laut colorhexa.com gar kein Grau, sondern "Light grayish cyan".

12.06.2023 - 19:18 Uhr

Zitat von perlfred

Wie gebe ich hier an, von wem dieses Zitat ist?

Das musst Du leider manuell machen, bzw. bei der "Zitieren" Funktion wird das automatisch gemacht.
Einfach "Zitat von XY" davor schreiben.

11.06.2023 - 18:34 Uhr

Mir ist nicht ganz klar, was Du in deiner Antwort sagen willst, besonders Verwirrend finde ich, wie Du die Aufzählungen verwendest. Willst Du ggf. Zitieren?

Der XAML-Code mit dem DataContext-Binding über das MainWindow ist aber gruselig, das würde niemals ein Review bei mir überstehen.
Ich hoffe (wegen deiner "Mit schlechtem Gewissen" Formulierung) ist klar, wieso? 😄

Und das Behavior:
So wie ich das meine, brauchst Du kein UCTextBoxAutoComplete mehr.
Du hast dann nur noch die TextBox und das Behavior, im Behavior wird auf Text-Änderungen gehört und zeigst ein eigenes Vorschau-Control als Adorner an.
Du kannst natürlich trotzdem ein eigenes Control bauen, aber dann würde ich das als CustomControl und ohne Adorner machen, die TextBox ist dann im Template definiert und Du kannst sie als TemplatePart abrufen.

11.06.2023 - 18:26 Uhr

Du willst also die Reihenfolge von Buchstaben überprüfen? A vor E und D vor T und so weiter?

Mach das nicht mit Regex.

Nimm dir deine char-Liste, frag den ersten Index ab und vergleiche die beiden Indizes.
Das ist bedeutend einfacher und vermutlich auch schneller.

11.06.2023 - 14:59 Uhr

Unter Attributes sind vermutlich nur Attribute, da wirst Du keine Logik finden.

Hättest du noch einen Tipp, wie ich da jetzt rangehe ?

Beim Entwickler der Software nachfragen, wie die sich das gedacht haben.
Wenn die sich gar nichts gedacht haben bzw. das gar keine offizielle Schnittstelle ist, dann bleibt nur Probieren und Reverse Engeneering.

11.06.2023 - 07:29 Uhr

Das sieht komisch aus ...
Du bindest den Text beim Aufruf des Controls an irgendein ViewModel.
Und in dem Control bindest Du den tatsächlichen Text wieder an irgendein ViewModel, diesmal hart im XAML definiert.
Eines der beiden Bindings ist Quatsch 😉 So wie Du das aufgebaut hast, darf dein UserControl kein ViewModel sehen.

"Richtiger" wäre, Du definierst eine Dependency Property, aber ein UserControl scheint für mich generell nicht der richtige Weg.

Ich würde zwei Wege in Betracht ziehen:

Nimm eine TextBox und arbeite damit, gerne auch im CodeBehind (solange die Vorschlagsdaten vom ViewModel kommen), das Auto Complete ist dann nur Logik, um auf Textänderungen zu reagieren und die Vorschau zu aktualisieren. Du könntest die Vorschau auch als Adorner implementieren, das wäre weniger fehleranfällig. Und die ganze Logik würde ich als Behavior implementieren, dann kannst Du es an verschiedenen Stellen nutzen, ohne ein eigenes Control zu haben. Geht auch als Attached Property, aber für komplexere Logik finde ich Behaviors bedeutend einfacher.

Oder Du erstellst doch ein eigenes Control, aber dann kein UserControl, sondern ein CustomControl.
Einfach eine normale Klasse für dein Control erstellen, die von TextBox oder TextBoxBase (musst Du schauen, was besser ist) ableitet.
Dort definierst Du dann deine ganze Logik und alle *zusätzlichen* Dependency Properties, die du brauchst, sowas wie Text erbst Du ja von der Basis.
Und daneben (oder wo auch immer) erstellst Du ein ResourceDictionary mit einem Style für dieses neue Control (ggf. kannst Du den TextBox-Style als Base nutzen). Der Style definiert dann z.B. auch ein Template, wo Du dann deine View für die AutoCompleteTextBox definieren kannst. Dort kannst Du dann mit TemplateBindings auf die DependencyProperties zugreifen.

Soweit ich das aktuell sehe, würde ich zum Behavior tendieren. Wenn Du den TextBox-Style als Style-Base nutzen kannst, wäre das CustomControl aber wiederum interessanter.

PS:

Nach dem Bild in deiner anderen Frage: Das ist definitiv ein Adorner 😃

10.06.2023 - 23:13 Uhr

In dem ganzen Beitrag ist nirgendwo ein ViewModel zu sehen, obwohl die Überschrift dieses suggeriert.

Man kann auch Bindings haben, ohne das ViewModel zu zeigen 😉
Die konkrete Implementierung des ViewModels ist unter Umständen gar nicht relevant, ist am Ende nur eine Property, meist mit irgendeinem MVVM-Framework implementiert. Es reicht zu wissen, wie die Property heißt und das sieht man am Binding.

Meine Frage ist nun, ist das der Standard und ist dass überhaupt noch MVVM?

Nein, ist kein MVVM.

MVVM unterscheidet (ich wähle bewusst etwas andere Bezeichnungen) View-Logik (View) und View-Business-Logik (ViewModel).
Alles, was Business-Logik ist, sollte prinzipiell gar nicht in der View auftauchen, aber das geht natürlich nicht überall und der Rest landet im ViewModel.
Die reine View-Logik, die unabhängig von der Business-Logik ist, die darf im XAML oder CodeBehind oder ähnlichen View-Technologien stehen.

Ein Beispiel für View-Logik wäre z.B. eine Drag&Drop-Sortierung einer Liste. Im ViewModel ist dann die ObservableCollection und im CodeBehind (oder einer anderen View-Technologie) wird das Drag&Drop behandelt, die die Items in der View neu anordnet und dadurch (indirekt) auch das ViewModel aktualisiert.

Die View-Logik darf natürlich auch im ViewModel stattfinden, allerdings gibt es meines Wissens nach keine gute Abstraktion um Drag&Drop, die brauchst Du aber, denn die View selber, also Controls und View spezifische EventArgs und so weiter, haben im ViewModel nichts verloren.

Bedenke immer:
Das ViewModel soll ohne View funktionsfähig sein.
Das funktioniert aber nur, wenn das ViewModel unabhängig oder nur von Abstraktionen abhängig ist.

die Eigenschaften eines UserControl's über DP's öffentlich zugängig gemacht. Das Binding innerhalb des UC's erfolgt entsprechend über den (Element)Namen des UC's und dem Namen der DP.

DendencyProperties sind dafür da, Controls auszulagern und mit eigenen Dingen einstellbar zu machen. Das kann z.B. dafür sein, ein Control an mehreren Stellen mit unterschiedlichen ViewModels nutzbar zu machen, oder Du möchtest einen Teil einer View auslagern, aber aus irgendwelchen Gründen (z.B. Übersicht) keine ViewModel-Bindings in dem Control haben, dann kannst Du das so machen. Ich persönlich nutze Dependency Properties aber fast nur als Attached Property, oder in einem Custom Control mit einem ausgelagerten Template, da kann man dann schön mit TemplateBindings arbeiten.

Ein Control als ViewModel zu missbrauchen, ist aber ganz sicher keine gute Idee.

10.06.2023 - 21:37 Uhr

Zitat von hkdd

Da ja nicht angespeichert ist, wo (an welchem Ort der  Erde) die  Installation stattfand, kann man die Zeit auch nicht korrekt zuordnen.

Egal, ist nicht relevant.

Abt schrieb doch, dass Windows die UTC Zeit speichert, die ist weltweit gültig.
Du musst es also als UTC lesen und als lokale Zeit ausgeben.

10.06.2023 - 18:16 Uhr

Das PropertyGrid arbeitet mit Reflection, es sucht die Daten aber nicht selbständig.

Das Programm sucht sich das also irgendwie auf eigene Weise und da können wir dann nicht helfen.
Du kannst dir aber ILSpy oder DnSpy herunterladen und selber nachforschen, wie die Daten gesucht werden.
Sobald das Objekt dem PropertyGrid bekannt ist, sollte es auch die Properties gruppiert nach der Gruppe anzeigen.

10.06.2023 - 10:07 Uhr

Generell frage ich mich, wozu das sein soll?

Würde es nicht reichen, die Version auf Namen zu mappen? Dann suchst Du dir einmal eine Tabelle raus und schreibst das in Code, das ist etwas arbeit, aber weit weniger fehleranfällig und komplex. Dann hast Du natürlich nicht die Info, von wem und wann es installiert wurde, aber brauchst Du das überhaupt?

09.06.2023 - 19:07 Uhr

was ich nicht verstehe ist, dass mein Form schon sichtbar wird, wenn ich es instantiiere, also ohne Show und Visible jemals genutzt zu haben

Weil Du Show benutzt hast.
Die Form zeigt sich nicht von alleine an, es muss Code geben, der das tut.
Oder Du hast irgendwas anderes, was das tut (ein externes Framework?), aber WinForms macht es nicht von alleine.

Am besten Du debuggst einfach durch deinen Code, dann findest Du schon die Stelle.

[Artikel] Debugger: Wie verwende ich den von Visual Studio?

09.06.2023 - 11:41 Uhr

Nein das geht nicht.

Aber das solltest Du dir anschauen:

Zitat von Palladin007

Was Du da hast, klingt nach einem PropertyGrid.
Das kann ggf. auch mit einem CustomTypeDescriptor arbeiten:
https://itecnote.com/tecnote/c-propertygrid-with-custom-propertydescriptor/

04.06.2023 - 10:56 Uhr

Beim Versuch, die Assembly selber zu laden, ist mir ein anderes Problem aufgefallen: Die DLL gibt's tatsächlich nicht.

Das ganze ist ein Vsix-Projekt und er legt die DLL zwar ins Output-Verzeichnis, aber nicht in die vsix-Datei, also kann sie natürlich auch nicht gefunden werden.

Fragt sich nur, warum die da nicht liegt, andere NuGet-Packages werden korrekt mit verpackt, nur die nicht - vielleicht weil er denkt, die gibt's schon in .NET und lässt sie deshalb weg?

Ich hab dazu das gefunden:
https://www.cazzulino.com/include-dlls-in-vsix.html

Zumindest bisher scheint das zu funktionieren, ich muss aber noch mehr testen.
Es ist außerdem "nur" die 4.2.0.1 Version, aber scheinbar nutze ich nichts, was Version 4.5.4 braucht.

03.06.2023 - 18:51 Uhr

Kann es sein,das du einfach bei der newVersion noch ein .0 anhängen musst?

Ich setzte bei mir auch gerne als oldVersion die Range von 0.0.0.0 bis zur spezifischen Version.

Hab ich beides schon probiert, gleiches Ergebnis.

03.06.2023 - 11:55 Uhr

Guten Mittag,

ich habe ein .NET 4.8.1 Projekt bestehend aus einem Startprojekt ohne SDK-Format und mehreren mit SDK-Format.
Einige Abhängigkeiten sind älter und bauen auf lokalen .NET Framework Referenzen auf und andere suchen auf NuGet.

Dabei ist die System.Threading.Tasks.Extensions.dll ein Problem, denn ein NuGet-Package braucht Version 4.5.4 (von NuGet) und andere Abhängigkeiten brauchen Version 4.2.0.1, sodass er Letzteres nicht findet.

Die konkrete Fehlermeldung:

System.IO.FileNotFoundException: Could not load file or assembly 'System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. Das System kann die angegebene Datei nicht finden.

Ich habe das NuGet-Package mit Version 4.5.4 auch im Startprojekt installiert, dann bekomme ich auch eine Warnung dazu. Diese Warnung ist aber etwas länger, daher lege ich sie als Datei in den Anhang.

Außerdem habe ich ein BindingRedirect erstellt:

<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
                <bindingRedirect oldVersion="4.2.0.1" newVersion="4.5.4" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>

Das ändert aber leider nichts.

Weiß jemand, wie ich das Problem lösen kann?

31.05.2023 - 23:26 Uhr

In den Einstellungen für die Forensignatur ist das Eingabefeld plötzlich sehr klein?
Nur 200 breit und füllt nicht mal im Ansatz den verfügbaren Platz.

30.05.2023 - 20:26 Uhr

um es erstmal so einfach wie möglich zu halten

Sicher, das geht dann mit MVVM.

Nochmal:

Avalonia wurde für MVVM gebaut.
Wenn Du dich weigerst, MVVM zu benutzen, machst Du es dir nur unnötig schwer.

Man kann es zwar auch ohne MVVM nutzen, aber dann musst Du eben alles das, was mit einem ItemTemplate super einfach geht, selber bauen.
In deinem Fall heißt das, dass Du anstatt des Bildes einen horizontal ausgerichteten StackPanel hinzufügen musst, was dann das Bild und den Text als TextBlock enthält.

30.05.2023 - 19:46 Uhr

Avalonia ist für MVVM gebaut:

https://mycsharp.de/forum/threads/118261/artikel-mvvm-und-databinding
https://docs.avaloniaui.net/guides/basics/mvvm

Der Datentyp ist object, damit Du dein ViewModel mitgeben kannst.
Zusätzlich definierst Du an der ListBox ein ItemTemplate, was definiert, wie die Daten aus deinem ViewModel angezeigt werden sollen.
https://docs.avaloniaui.net/docs/controls/listbox

Wenn Du ein Bild anzeigen willst, brauchst Du ein Image, dem Du dann eine Source zuweist. Das "Bitmap" wäre dann deine Source.

Das Standartverhalten ruft einfach ToString auf, daher das Verhalten, was Du beobachtest.

28.05.2023 - 21:36 Uhr

Du kannst jederzeit eine eigene Form bzw. ein eigenes Window anzeigen.
Aber das musst Du selber machen, einen Button in die bestehende View integrieren ist nicht so einfach.

28.05.2023 - 20:34 Uhr

Wenn "Komponente1" und "Komponente2" die Gruppen sind, wie Du sie im DisplayAttribute angibst, dann geht es nicht.
Jede Property kann nur ein DisplayAttribute haben, also auch nur eine Gruppe, was bedeutet, dass Du für jede Gruppe die Properties copy&pasten musst.

Eine Möglichkeit gäbe es aber vielleicht noch:

Was Du da hast, klingt nach einem PropertyGrid.
Das kann ggf. auch mit einem CustomTypeDescriptor arbeiten:
https://itecnote.com/tecnote/c-propertygrid-with-custom-propertydescriptor/

Wie genau das dann umgesetzt wird, müsste ich mich aber auch erst wieder einarbeiten - ist ewig her, dass ich das mal genutzt habe.

28.05.2023 - 19:56 Uhr

Vererbung.

Oder Du erstellst die Criterien unabhängig von deinen UI-Properties.
Der User stellt also XY ein und Du erstellst anhand der Einstellungen deine Kriterien-Objekte.

28.05.2023 - 19:26 Uhr

Mir ist auch nicht klar, was Du uns sagen willst.

Eigentlich sollte so jede Form von Prüfung möglich sein.

Zur Not copy&pastest Du halt ein paar Klassen und passt sie nach abweichenden Anforderungen an, oder Du arbeitest mit Vererbung.

28.05.2023 - 19:13 Uhr

Attribute sind Metadaten.
Sie stehen einfach nur in der Assembly und sonst nichts.
Spannend ist, dass man sie und die Daten mit Reflection auslesen kann.
Du kannst Teile in deinem Code damit markieren, viele Programme und auch .NET selber nutzen sie, um das dann zu finden und ggf. Einstellungen auszulesen.

handelt es sich um eine  methode zum befüllen/lesen der Klassenvariable _selection

Das ist eine Property mit get- und set-Accessor. Im Hintergrund sind das dann zwei Methoden.
Aber Properties sind nicht einfach "nur" Methoden, die werden auch technisch unterschieden.

Wäre es prinzipiell möglich in der eigenen DLL ein kleines GUI zu entwerfen und dafür zu sorgen, dass dieses aus der 3rd party app heraus aufrufbar ist?

Wenn die Anwendung einen vorgesehenen Weg dafür bietet, dann kannst Du den nutzen.
Ohne offiziellen Weg wird's schwieriger, möglich sicher, aber dann eher Hacken und sicher keine gute und langfristige Lösung.

28.05.2023 - 11:29 Uhr

Aktuell ist .NET 7, .NET 8 gibt's als Preview, .NET 6 hat Long-Term-Support.
Achte bei den Projekt-Vorlagen darauf, ob da ".NET Framework" in Klammern steht, oder nicht.
Mit ".NET Framework" in Klammern ⇒ Alte Welt
Ohne ".NET Framework" in Klammern ⇒ Neue Welt
Nicht gerade intuitiv, aber so ist es eben.

Du solltest die neue Welt nehmen.
Konsole gibt's da natürlich auch, wie auch WPF, ASP.NET, etc.
Du wirst vermutlich von den Top-level statements überrascht werden. Kannst Du beim Projekt erstellen einstellen, oder mit deinem Code ersetzen, ist aber Geschmackssache und nicht wichtig.

Und stell auf Englisch um, ggf. musst Du die Sprache im Visual Studio Installer installieren.
Die meisten relevanten Quellen sind auf Englisch, da lohnt es sich, auch mit Englisch zu arbeiten.


Und dein Problem:

Der Fehler ist genau, dass die Konsole und die Programmausführung nach der vollständigen Eingabe beim Release-Debuggen und dem "normalen" Debuggen sich einfach schließt.

Das klingt, als wäre dein Programm einfach zuende:
[FAQ] Konsole schließt sich sofort nach dem Start
Im Release-Build verhält sich Visual Studio an dem Punkt anders, wobei das bei mir seit Win11 auch nicht mehr der Fall ist, da startet er das Terminal und das bleibt dann auch offen.
Also entweder Du hinderst das Programm daran, sich zu beenden (Console.ReadLine, oder Console.ReadKey), oder Du baust eine Funktion an, dass es z.B. immer in's Menü zurückkehrt. Letzteres wäre definitiv verständlicher für den Anwender.

Oder Du hast einen Bug in deinem Code, der abhängig von Debug vs. Release ist.
Hält er an, wenn Du am Anfang der Main-Methode einen Breakpoint setzt?
Wenn ja, dann debugge bis zu dem Punkt, wo sich das Programm beendet, dann weißt Du, wo der Fehler ist.
[Artikel] Debugger: Wie verwende ich den von Visual Studio?

Das mit dem Publishen funktioniert leider auch nicht. Ich habe da als Speicherort meinen Desktop ausgewählt, und das über CD-Rom es installiert wird und das Programm nicht nach Updates sucht.

Klingt so, als hättest Du was falsch gemacht, eigentlich funktioniert das Publishen ins Dateisystem ziemlich einfach.
Du musst natürlich auch einstellen, dass er nur in einen Ordner publishen soll, ansonsten versucht er noch andere Dinge, die zu diesem Fehler führen könnten.

27.05.2023 - 20:02 Uhr

Nur leider funktioniert das Debuggen nicht weder als Release noch als "normales" Debuggen.

Was heißt "funktioniert nicht"? Das ist keine Fehlerbeschreibung.

Ich habe als CPU "Any CPU" ausgewählt mit der neusten .NET-Framework Version

Lies dir das durch: [FAQ] Das .NET Ökosystem - .NET, .NET Core, .NET Standard, NuGet und Co

Du schreibst ".NET-Framework", was nach der alten Umgebung klingt, außerdem muss man in der Neuentwicklung normalerweise kein AnyCPU auswählen.

Für dein Problem sollte das aber nicht verantwortlich sein, das alte .NET Framework funktioniert immer noch, ist bloß alt und wird nicht mehr weiterentwickelt. Umsteigen solltest Du natürlich trotzdem, bei deinem Projekt würde ich mich sehr wundern, wenn es relevante Unterschiede im C#-Code gibt.

Nur möchte ich die Anwendung weitergeben und ohne das Debuggen funktioniert das ja leider nicht

Wer sagt das?
Geht definitiv. Sowohl beim Debuggen, aber auch beim "Starten ohne Debugger" wird eine Version kompiliert, die ohne Visual Studio nutzbar ist, die liegt im bin-Ordner im Projekt.
Du solltest aber lieber die Publish-Funktion nutzen: Tutorial: Publish a .NET console application using Visual Studio
Das "console application" ist nicht weiter relevant, für Desktop-Anwendungen sollte das genauso funktionieren, im Web gibt's aber mehr, daher vermutlich die Unterscheidung.