Laden...

Mausklick auf ein Element das wiederum Teil vieler im Benutzersteuerelement ist

Erstellt von AlphaCS vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.708 Views
A
AlphaCS Themenstarter:in
15 Beiträge seit 2017
vor 6 Jahren
Mausklick auf ein Element das wiederum Teil vieler im Benutzersteuerelement ist

Folgender Ausbau:

Ich habe ein Benutzersteuerelement Kategorie, das aus der Datenbankabfrage ein <List<List<object>> Typ holt.

Im Benutzersteuerelement Kategorie sind weitere Benutzersteuerelemente wie:
* Textliste
* und vordefinierte Steuerelemente von MSVS 2015 , hier Textbox

In der Textliste befinden sich wiederum dynamisch erzeugte Benutzersteuerelemente in einem StackPanel die u.A. folgende Eigenschaften haben:
id, inhalt, ect. und ein Steuerelement, was aus XAML-Code ein Icon erzeugt.
die Eigenschaften ergeben sich aus der Datenbankabfrage. Je nach Listenposition eben unterschiedliche IDs und Inhalte.

Nun habe ich folgende Probleme:
Ich möchte per Klick auf eines der Icons folgendes machen:

Im Benutzersteuerelement Kategorie möchte ist feststellen welches der Icons in der Textliste geklickt wurde. Es soll eine Methode in Kategorie sein die das Mausklick-Ereignis entgegennimmt.

Wie man ein Mausklick_Ereignis anlegt ist mir bekannt. Wie bekomme aber im sender-Objekt heraus, woher der klick kommt?

Der sender , soweit mit bekannt ist, übergibt sich nur selber als Objekt.
Wenn ich das Ereignis direkt auf das Icon lege, habe ich zwar auch ein Ereignis aber ich kann das nicht außerhalb des Benutzersteuerelementes ansprechen, also noch nicht. 😃

Ich muß auch dazu sagen, das ich beim Lesen immer wieder an meine Grenzen stoße, teilweise oder gar insgesamt scheinen viele Autoren Fachbegriffe im akademischen Stil perfekt zu beherrschen, aber ich komme nicht auf ein Ergebnis. Ich weiß nicht mal ob **Routet ** oder **Delegate ** hier das richtige ist. Mir fehlt sowohl die Anschaulichkeit als auch Analogien zu bereits bekannten dingen um das zu verstehen.

Gibt es denn ein 0815 minimalistisches Beispiel wo man das mal am lebenden Patienten ansehen kann?

2.079 Beiträge seit 2012
vor 6 Jahren

Schau dir mal die EventArgs an.

Das sind RoutedEventArgs und da gibt's die Properties OriginalSource und Source.

Eine von den beiden Properties wird vermutlich das enthalten, was Du suchst.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

A
AlphaCS Themenstarter:in
15 Beiträge seit 2017
vor 6 Jahren

Ich hab beim Suchen das hier gefunden.
https://dotnet-snippets.de/snippet/routedevent-erstellen/1284

Ich weiß leider nicht wo man das genau reinschreibt.

Mein Problem ist, ich verstehe nicht, was da genau gemacht wird.

Ich bin immer davon ausgegangen, dass ich eine Methode habe wo ich das Ereignis abfangen und auswerten kann.

Das steht jetzt direkt im Quellcode bei mir Benutzersteuerelement Kategorie:


		public static readonly RoutedEvent MySpecialClickEvent = EventManager.RegisterRoutedEvent(
			"MySpecialClick",
			RoutingStrategy.Bubble,
			typeof(RoutedEventArgs),
			typeof(MainWindow)
		);

		public event RoutedEventHandler MySpecialClick
		{
			add
			{
				this.AddHandler(MySpecialClickEvent, value);
			}
			remove
			{
				this.RemoveHandler(MySpecialClickEvent, value);
			}
		}

Was ist z.b. MySpecialClick? Eine definierte Methode? Falls ja, wo müsste die genau hin und wie aussehen?
Ich vermute mal das MainWindow noch in den typ des Benutzersteuerelements umbenannt werden muss ?

2.079 Beiträge seit 2012
vor 6 Jahren

Zur Frage im letzten Satz: Ja, muss der Typ des "besitzenden" Controls sein.

Aber Du brauchst gar kein eigenes RoutedEvent, das Click-Event ist bereits ein RoutedEvent.
Es bietet also auch die RoutedEventArgs.
Wenn der EventHandler automatisch generiert wird (gibt CodeSnippets in VS dafür und der Designer kann das auch) heißt der Parameter meist einfach nur "e".

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

A
AlphaCS Themenstarter:in
15 Beiträge seit 2017
vor 6 Jahren

Click-Event gibt es bei meinem eingesetzen Benutzersteuerelement nicht aber ich kann MouseDown benutzen. Grundsätzlich gibts fast kaum Click-Ereignisse, obwohl man die nicht nur beim Button braucht. Vermutlich auch nur ein zusammengesetzter Typ aus Up und Down? k.A. egal...

Also steht, was ich suche im 'e' ? ich hab die ganze Zeit das sender-Ding debuggt.


Nach Erfolglosen Versuchen formuliere ich mal meine Frage um:

Was muss man denn genau machen um an ein Property eines Benutzersteuerelements zu gelangen, wenn man auf dieses geklickt hat und im Übergeordneten Bereich die Auswertung braucht?

Im Grunde brauch ich z.b. nur die ID aus der Datenbank, die ebenso im Benutzersteuerelement liegt, weil ich sie dort gespeichert hab um später zu unterscheiden, welches der Elemente ich angeklickt habe.

2.079 Beiträge seit 2012
vor 6 Jahren

Ach Du hast gar kein Click-Event
Dann musst Du das wohl wirklich selber machen 😄 Aber vermutlich hast Du recht und das Click-Event ist nur eine Kombi aus den Genannten

Aber auch die Mouse-Events sind RoutedEvents und bieten RoutedEventArgs.
Bei denen sind's bloß Ableitungen davon.

Also ja: Schau mal durch die e-Variable, da sollte alles nötige zu finden sein.

Allgemein klingt aber auch dein zweiter Erklärungs-Versuch nach einer schwierigen bis schlechten Struktur deiner Anwendung.
Speziell bei WPF ist meist das MVVM-Pattern sehr zu empfehlen, es vereinfacht vieles.
In dem verlinkten Artikel solltest Du eigentlich alles finden, was Du so brauchst, inklusive Beispiel-Projekt.

Wenn Du das richtig umsetzt, dann musst Du gar nicht mehr in EventHandlern und mit Controls umher hampeln und auf tausend Umwegen deine Daten suchen. Dass das schnell unübersichtlich werden kann, hat man ja schon bei WinForms gemerkt und WPF ist der Versuch, das Problem zu lösen. Klappt eben nur mit MVVM wirklich gut ^^
Die wirkliche Arbeit passiert dann nur noch direkt oder indirekt im ViewModel, die View interessiert das nicht mehr, die sagt nur noch, wann was passieren soll - also beim Click.

Etwas schwierig wird's, wenn Du keine ClickCommand-Property dort hast, wo Du es brauchst.
Dann kannst Du aber auch einfach wieder den Umweg über den EventHandler gehen und die entsprechende ViewModel-Methode aufurfen.
Ist nicht ganz so schön und manche sagen, das ist nicht MVVM-Konform, ich sehe das aber nicht so kritisch.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

A
AlphaCS Themenstarter:in
15 Beiträge seit 2017
vor 6 Jahren

Ich dachte bisher immer, wenn man Steuerelemente aus anderen zusammenbaut wäre das genial, da man so die Komplexität verringert und den Code übersichtlich hält?

Im Moment such ich noch keine "saubere" sondern überhaupt eine Lösung. Denn ich bin bisher nicht vorangekommen und sitze nun schon 3 Tage am gleichen Problem. Leider hab ich nicht den Luxus von Zeit und muss daraus meine 1. Projektarbeit inkl Dokumentation gestalten. Da ist es nicht so tragisch etwas unperfekten Code abzuliefern als gar nichts.

Ich werd mir aber mal die Seite ansehen, nur seh ich jetzt schon keine Lösung für meine bisherige Arbeit darin, denn mein Problem ist auch, dass ich vom hundertsten ins tausendste komme ohne weiter zu kommen. Ich kann auch nicht immer alles komplett neu Umplanen. Der Umfang der Dokumentation und Einarbeitung über MVVM übersteigt bei weitem die Zeit von 70h die ich habe. Ich muss das jetzt einmal durchziehen.

2.079 Beiträge seit 2012
vor 6 Jahren

Du baust die ja auch aus anderen Zusammen.
Es kann auch klug sein, einzelne Teile deiner View in ein eigenes UserControl zu legen. Das spart unter Umständen redundanten Code oder macht die Nutzung übersichtlicher.
Es kann aber auch stören. Wie mit so vielen Dingen hat alles Vor- und Nachteile, Du solltest immer beide Seiten gegeneinander aufwiegen.

Aber gut, wenn nicht viel Zeit da ist, ist so ein Umschwung natürlich unpraktisch
Wobei ich noch von keinem Projekt gehört habe, bei dem die 70h gereicht haben. Haben die Lehrer in meiner Ausbildung auch ständig gesagt.

Hast Du denn mal nach geschaut, was in den EventArgs drin steht?
Mehr Infos als in den EventArgs bekommst Du nicht.

Die Alternative ist, dass Du den Controls Namen gibst und dann "per Hand" die Controls bzw. deren Content suchst, bis Du das richtige Control findest.
Das ist aber sehr fehleranfällig, besonders wenn Du mal was an der View ändern willst.

Oder - wenn die betroffenen Controls dynamisch erzeugt werden - Du sammelst die beim Erzeugen in einer Liste.

Wenn Du über die EventArgs oder auf dem Umweg "Selber suchen" nicht zum Ergebnis kommst, dann wirst Du dich wohl oder übel damit abfinden müssen, dass Du umstrukturieren musst.

Tatsächlich ist aber das Problem, an dem Du jetzt gerade sitzt, der Grund, warum es einige Patterns gibt. Da gibt's noch weitere, wie z.B. die Drei-Schichten-Architektur

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

A
AlphaCS Themenstarter:in
15 Beiträge seit 2017
vor 6 Jahren

Ich habs jetzt erstmal so gemacht, dass ich die Eigenschaften des Event-Bubbling nutze.
Ich habe 2 Events gesetzt.
Ein Mouse-Down-Event direkt im Steuerelement (Einzelnes Listenelement mit Icon und Text )

  • Das löscht auf Grundlage der mitgegebenen ID den Datenbankeintrag

Ein Mouse-Down-Event direkt im Steuerelement , wo diese Liste als eigenes Benutzersteuerelement drin steht

  • Das initialisiert meine Liste neu und damit ist sie immer aktuell

Im Grunde habe ich festgestellt, das ich hier einen zentralen Zugriff aus ausgewählte Eigenschaften brauche. Bei meinen Daten löse ich das über die SQLite-Datenbank, aber für internes Weiterreichen muss ich sowas wie eine Klasse machen die von allen anderen Klassen aus erreichbar ist.

Oder ist muss eine Liste als Objekt anlegen aus den ich meine dynamisch erzeugten Steuerelemente referenziere. Ich glaub letzteres klingt sinnvoll. ^^

Ich danke für die Hilfe. Hier waren interessante Sachen dabei, aber zu allem werd ich nicht so fix kommen. Eigentlich wäre es cool mal ein komplettes Jahr nur C# intensiv zu lernen. 😃 Aber dafür ist nie Zeit. Ich nutze jeder freie Minute, die ich hab. Leider kommt man allein nicht so weit, weil einem die Rückkopplung fehlt, die ein Dozent oder Ausbilder liefern könnte. eigentlich ist das hier bei uns alles irre. Ich bin in Ausbildung um Fachinformatiker zu werden und hab kaum Zeit zum programmieren, weil man uns noch ein Haufen Müll vermittelt den wir nie mehr im Leben brauchen werden. 😦

2.079 Beiträge seit 2012
vor 6 Jahren

Mir ist nicht so ganz klar, was Du meinst O.o
Mir ist aber auch nicht ganz klar, wie deine View überhaupt aufgebaut ist 😄

Eben kam mir aber eine Idee, die vielleicht einiges einfacher macht.

<Button Click="DeinButtonCLickEvent">
    <Button.Template>
        <ControlTemplate>
            <!-- Hier dein Content -->
        </ControlTemplate>
    </Button.Template>
</Button>

Den Button sieht man dann nicht mehr, sondern nur noch das, was Du anzeigen möchtest.
Jeder Click irgendwo innerhalb dieses Bereichs landet aber beim Button und wird über das angegebene Click-Event gehandelt.

Wenn die Buttons dynamisch erzeugt werden, dann kannst Du ein Objekt, was irgendwo in diesem Template angezeigt werden soll und wo deine Daten drin stehen, in der Tag-Property verstauen.
Im Click-Event bekommst Du immer den Button und über die Tag-Property findest Du auch ganz einfach die Infos die Du brauchst.

Bedenke aber:
Diese Lösung ist nicht gerade ordentlich.
Wenn sie sich auf deinen Fall anwenden lässt, dann ist sie nur eins: Schnell und einfach
Das gleiche Ergebnis lässt sich auch mit MVVM erreichen, bloß dass Du da alles sauber voneinander getrennt hast.

Was deine Ausbildung angeht:
Mein jetziger Arbeitgeber hat mal gesagt, dass er es sehr merkwürdig finden würde, wenn ich erzählen würde, ich wäre in meiner Ausbildung sinnvoll ausgebildet worden 😄
Das passt auch zu meiner Erfahrung:
In der Ausbildung lernst Du hauptsächlich den Berufsalltag kennen und damit umzugehen. Wenn Du Glück hast kannst Du auch praktische Erfahrungen sammeln.
In den meisten Fällen ist's aber anders: Du bist eine billige Arbeitskraft die man da einsetzt, wo sie gerade gebraucht wird.
Vergiss dabei aber auch nicht, dass dieser nutzlose Müll sehr wichtig sein kann. In einem Unternehmen gibt's eben nicht nur die Arbeit nach Schema F, Du musst auf das reagieren was rein kommt und das kann auch mal ziemlich sinnlos wirken.

Viel wichtiger ist eher, dass Du es schaffst, eben ohne die von dir genannte Rückkopplung zu lernen.
Nach der Ausbildung wirst Du fest stellen, dass das, was Du bisher weist, nur ein winzig kleiner Teil ist und Du noch sehr viel lernen musst.
Später wird dir aber niemand beim Lernen helfen, das darfst Du schön alleine machen.
Wenn Du im Betrieb nicht genug Zeit hast, dann solltest Du das Zuhause machen. Wenn es Fragen gibt, dann kannst Du ja immer noch hier fragen.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.