C# Objekt durch Wert eines strings ansprechen

papanini

Ensign
Registriert
Feb. 2014
Beiträge
206
Hallo liebe Community :D

Derzeit versuche ich mich an einem Programm (Spiel) und verzweifle gerade bei der Suche einer vermutlich recht simplen Lösung für ein "großes" Problem :freak:

Vorab: Ich arbeite mit WPF und XAML. Ich habe in meinem WPF Fenster sehr viele (am Ende ca. 200-300) "Leuchten", welche je nach Situation in unterschiedlichen Farben (anderes Image) leuchten sollen. Ich habe mich dafür entschieden innerhalb eines Stackpanels jede Leuchte als Image darzustellen (einfacher möglich?):
Code:
<StackPanel Name="stkMain" Orientation="Horizontal" DockPanel.Dock="Top" Background="Gray" Height="724" Width="1280">
            <Image Name="rl001_1" Source="Templates/Schiene_Leuchte2.png" Height="4" Width="6" Margin="-40,0,0,0"/>
            <Image Name="rl001_2" Source="Templates/Schiene_Leuchte2.png" Height="4" Width="6" Margin="-24,0,0,0"/>
            <Image Name="rl001_3" Source="Templates/Schiene_Leuchte2.png" Height="4" Width="6" Margin="-8,0,0,0"/>
            //...

Namensgebung des Images an dieser Stelle bitte ignorieren :lol:
Nun habe ich im C# Coding ein einfaches string Array, welches die Namen aller vorhandenen Leuchten beinhaltet (rl001_1,...). Einem weiteren string wird, teilweise random, eine Leuchte zugewiesen, so bekommt die Variable beispielsweise den Wert "rl001_2".

Kurz und knapp: Wie kann ich es bewerkstelligen genau die Leuchte anzusprechen dessen Name in dem string steht? Klar... ein 0815 Vergleich mittels
Code:
if(value == rl001_1)
//...
else if(value == rl002_2)
//...
würde natürlich funktionieren, ist aber bei 200-300 Leuchten eher etwas unschön. Da gibt es doch sicherlich eine einfachere Lösung dass ich das Image ansprechen kann (z.B. Source ändern) das denselben Namen wie den Wert meines strings hat oder?

Hoffe ich konnte mein Problem verständlich darstellen.

Danke schon mal im voraus!
 
Für so etwas nimmt man ein Dictionary | https://www.dotnetperls.com/dictionary.

Deine Variante ist übrigens sehr, nun ja, aufwendig. Das Generieren der Images würde ich per Code machen.

Code:
for (var x = 0; x < 10; x++)
{
   for (var y = 0; y < 10; y++)
   {
       var image = new Image(...);
       image.Position = new Position (x*10, y*10);
       container.Add(image);
       dictionary.Add(x*10+y, image);
   }
}
 
Vielen Dank @Bagbag für den Tipp, das Dictionary hatte ich schon total aus den Augen verloren :freak:
Das macht es natürlich einfacher. Die Images werde ich dennoch zum größten Teil selbst generieren, da die Position nicht "in Reihe" sondern recht willkürlich ist :/

Dennoch ist meine Hauptfrage noch nicht beantwortet. Beispiel folgend: Im Dictionary :D (beispielhaft "d") sind alle Signale als string hinterlegt.
Code:
if(d.ContainsKey(z1.position))  //z1.position = "rl001_2"
                //Vorhandenes Image "rl001_2" ansprechen???

In z1.position ist nun ein zufälliger Wert, in diesem Fall "rl001_2" drin. Dieser Wert ist auch im Dictionary vorhanden und wird gefunden, aber wie spreche ich nun das vorhandene Image direkt an? Mir ist ja nicht bekannt welcher Wert sich in z1.position befindet? Ich möchte einfach bei dem entsprechenden Image die Source ändern :D
 
Image i = (Image) FindName("r1001_1");
 
Ich habe das zwar auch noch nicht genutzt, aber ich würde es mal mit d.TryGetValue(z1.position), oder d[z1.position] versuchen...
Als Rückgabe solltest du direkt das gewünschte Objekt bekommen.

Du solltest aber auch das dictionary so erstellen, dass es nicht nur Strings speichert (wirst du aber wohl gemacht haben):
Dictionary<string, Image> d = new Dictionary<string, Image>();
 
Zuletzt bearbeitet:
Wenn Du den Namen hast, kannst Du Reflektion benutzen. Beispiel:

Code:
<Grid>
   <Image x:Name="image01"></Image>
   <Image x:Name="image02"></Image>
</Grid>

Die Referenz auf image01 bekommt man dann mit:
Code:
var img = (Image)typeof(UserControl1).GetProperty("image01").GetValue(this, null);

Edit: Habs nicht getestet. Falls die Bilder nicht als Property angelegt werden muss man GetField anstatt GetProperty benutzen.
 
Zuletzt bearbeitet:
Code:
dictionary.Add("apple", 1);
int value = dictionary["apple"]; //value ist 1

oder Analog dazu mit einem Image:

Code:
dictionary.Add("rl001_2", rl001_2);
Image image = dictionary["rl001_2"]; //image ist die Instanz von rl001_2


wobei in diesem Fall das von umask007 wohl passender ist.


Ich an deiner Stelle würde dann eine Datei anlegen, in der die Positionen stehen und diese Auslesen und dann per Code dynamisch generieren. Gerade bei einem Spiel macht so etwas doch Sinn, um bspw. verschiedene Levels/Karten/was auch immer haben zu können. Wäre jedenfalls wesentlich übersichtlicher als deine jetzige Variante.

Und noch eine Ergänzung zu meinem 1. Post:
Da der Key ein Interger ist, der von 0 - anzahl der Images geht, würde da auch ein einfaches Array ausreichen.
 
In WPF greift man normalerweise nicht vom Code auf die GUI zu. Sinnvollerweise verwendest du Bindings.

Erstelle dir eine Klasse Leuchte mit den Eigenschaften die du brauchst (z.B. den Namen der Bilddatei), leg dir im Code eine Liste mit deinen Leuchten-Objekten an, binde die Liste als ItemsSource an ein ItemsControl in XAML und definiere dir ein passendes ItemTemplate.

Mit Reflections oder ähnlichem machst du dir selber keine Freude.
 
Vielen Dank für die zahlreichen Tipps, konnte mit der Variante von Bagbag schon einen vollen Erfolg erzielen :D
Damit ist mein Problem gelöst, werde aber für den Lerneffekt natürlich die anderen Tipps ebenfalls noch versuchen umzusetzen!

Besten Dank :cool_alt:
 
Zurück
Oben