Lokalisierung von WinForms Anwendung - speziell ListBox Elemente

LutzBerillio

Grünschnabel
Hallo alle zusammen,

ich bin gerade dabei mich mit Lokalisierung von Windows Forms Anwendungen auseinander zu setzen und eine kleine Beispiel-Anwendung in C# zu schreiben.

Bin da auch schon relativ weit mit gekommen:
Habe eine Forms-Anwendung erstellt und über "Add --> new Item --> Resource File" eine Default-Resource-Datei erstellt. Dort hab ich dann meine Texte eingetragen (z.B. RandomLanguageButton - "Zufällige Sprache Default", etc).

Nun habe ich im Win-Explorer die Datei mehrfach kopiert und in <Anwendungsname>.<Name des Default-File>.<Culture>.resx umbenannt, also z.B. "ResxReader.Strings.de.resx". Diese Dateien habe ich dann sprachlich angepasst und über ResGen.exe und al.exe laufen lassen um mir Satelliten-Assemblies zu generieren.
Die Satelliten-Assemblies habe ich dann ins Applikationsverzeichnis kopiert.

Um zur Laufzeit das Programm übersetzen zu können, iteriere ich im Code über alle Controls rekursiv durch und hole über den Control-Namen aus dem Resource-Manager die notwendige Übersetzung. Habe auch einen MenuStrip drinne, den ich mit einer eigenen rekursiven Routine übersetze. (So wie hier im Forum auch schonmal diskutiert).

Nun langsam zu meiner eigentlichen Frage:
Ich habe eine ListBox in meiner Form hinzugefügt. Diese Listbox soll einfach nur Sätze anzeigen. In meiner Default-Resource-Datei (Strings.resx) habe ich hierzu Sentence1 bis Sentence5 hinzugefügt und auch meine anderen 5 Sprachen dahingehend angepasst und wieder als Satelliten Assembly übersetzt.

Initial setze ich nun meineListbox.Items.add(Strings.Sentence1). Das ist natürlich nicht sonderlich gut, die variablen Items einer ListBox über die Wrapper-Klasse auszuwählen. Also dachte ich mir ich kann irgendwie was basteln, dass es mir erlaubt dynamischer auf die Übersetzungen mit dem Resource-Manager zuzugreifen (wie ich es ja auch mit den Controls mache).
Allerdings stellt mich das ein wenig vor ein Rätsel...

Bei den Controls hab ich es so gemacht, dass ich - wie oben beschrieben - im ResourceManager das Control über seinen Namen referenziere:
Code:
actControl.Text = Strings.ResourceManager.GetString(actControl.Name);

Ich steh voll am Schauch, wie ich das für so dynamisch wachsende oder auch schrumpfende "Text Mengen" wie z.B. die Einträge in der besagten ListBox machen soll? Es ist ja durchaus ein möglicher Anwendungsfall, dass in so eine ListBox Inhalte zur Laufzeit hinzugefügt werden oder gelöscht werden. Und ich kann ja auch nicht über den Namen der Items im ResourceManager referenzieren (oder kann ich irgendwie?)

Jetzt hatte ich schon die Idee, die Items evtl. mit einem CultureInfo zu taggen. Weiß aber nicht so wirklich wie ich da vorgehen soll :confused:

Hoffe mir kann da jemand auf die Sprünge helfen, und VIELEN DANK schonmal für's lesen meines (doch nicht ganz so kurz gewordenen) Beitrags ;)
 
Zuletzt bearbeitet:

LutzBerillio

Grünschnabel
Habe mir jetzt was gebastelt was mein Problem löst:

Die Listbox wird nun anstatt mit einfachen Strings mit Transferobjekten gefüllt. Diese Transferobjekte bieten mir nun Display, Value und Name Member. So kann ich als Value member beispielsweise die aktuelle CultureInfo mitgeben und auch einen Namen über den ich das ListItem in den Sprachdateien referenzieren kann.

Meinen rekursiven Durchlauf zu Übersetzung hab ich um
Code:
if (con is ListBox)
{
     this.ChangeLanguageListBox(((ListBox)con));
}
erweitert.

Dann kam das nächste "Problem". Und zwar lässt sich der Display-member von den ListBox Items anscheinend nicht so einfach "refreshen". Allerdings benutzt die ListBox beim hinzufügen von Elementen die ToString() Methode um den Display-member zu aktualisieren.

Daher hab ich dann folgendes gebastelt:
Code:
private void ChangeLanguageListBox(ListBox box)
{
	box.BeginUpdate();

	// remind selection
	int selection = box.SelectedIndex;
			
	for (int i = 0; i < box.Items.Count; i++)
	{
		((ItemObject)box.Items[i]).Value = Thread.CurrentThread.CurrentUICulture;
		((ItemObject)box.Items[i]).Display = Strings.ResourceManager.GetString(((ItemObject)box.Items[i]).Name);

		box.Items.Insert(i, box.Items[i]);
		box.Items.RemoveAt(i + 1);
	}

        // set back selection
        box.SelectedIndex = selection;

	box.EndUpdate();
}

Vielleicht hilfts ja mal irgendwem weiter...