Michael Edwards
Michael Edwards

Reputation: 6518

Getting a set of values from a resource file in C#

I am storing a set of values in a resource file (resx) and have namespaced the values like so:

Form.Option.Value1 | Car 
Form.Option.Value2 | Lorry
Form.Option.Value3 | Bus
Form.Option.Value4 | Train

If there a way with the System.Resources.ResourceManager class to retrieve all these values in one go. I am look for a sort of get by prefix method:

ResourceManager manager ...
IEnumerable<string> values = manager.GetStringsByPrefix("Form.Option");

The reason for doing this is that we have a form with a dropdown where the values may need to change depending on the culture.

Also is it possible to get back the string values as key value pairs so I can get the name of the resource and its value, e.g.:

IEnumerable<KeyValuePair<string,string>> values = manager.GetPairWithPrefix("Form.Options")

Upvotes: 0

Views: 4280

Answers (5)

Michael Edwards
Michael Edwards

Reputation: 6518

Thanks for the response, I solved this by sub-classing the ResourceManager and adding a new method:

public class ResourceManager : System.Resources.ResourceManager
{
    public ResourceManager(Type resourceSource)
        : base(resourceSource)
    {

    }

    public IEnumerable<string> GetStringsByPrefix(string prefix)
    {
        return GetStringsByPrefix(prefix, null);
    }

    public IEnumerable<string> GetStringsByPrefix(string prefix, CultureInfo culture)
    {
        if (prefix == null)
            throw new ArgumentNullException("prefix");
        if (culture == null)
            culture = CultureInfo.CurrentUICulture;
        var resourceSet = this.InternalGetResourceSet(culture, true, true);

        IDictionaryEnumerator enumerator = resourceSet.GetEnumerator();
        List<string> results = new List<string>();

        while (enumerator.MoveNext())
        {
            string key = (string)enumerator.Key;


            if (key.StartsWith(prefix))
            {
                results.Add((string)enumerator.Value);
            }
        }
        return results;
    }
} 

Upvotes: 1

BlueMonkMN
BlueMonkMN

Reputation: 25601

Although the IDE for editing resx files doesn't support it, you can add string arrays (and I suspect any serializable class) to an resx file:

string outPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
outPath = System.IO.Path.Combine(outPath, "MyResources.resx");
using (System.Resources.ResXResourceWriter rw = new System.Resources.ResXResourceWriter(outPath))
{
   rw.AddResource("ComboBox1Values", new string[] { "Car", "Train" });
   rw.Generate();
   rw.Close();
}

In the output file you'll see something like:

<data name="ComboBox1Values" mimetype="application/x-microsoft.net.object.binary.base64">
  <value>AAEAAAD/////AQAAAAAAAAARAQAAAAIAAAAGAgAAAANDYXIGAwAAAAVUcmFpbgs=</value>
</data>

Upvotes: 0

Henk Holterman
Henk Holterman

Reputation: 273169

You should probably reconsider the format. Like

 Form.Option.Value = Car;Lorry;Bus;...

Upvotes: 1

BlueMonkMN
BlueMonkMN

Reputation: 25601

If you use the localization feature built into Visual Studio / .NET Framework to localize your forms (including combo box lists) it generates code like this:

Found in Form1.de.resx:

<data name="comboBox1.Items" xml:space="preserve">
  <value>Auto</value>
</data>
<data name="comboBox1.Items1" xml:space="preserve">
  <value>Bahn</value>
</data>

Found in Form1.resx:

<data name="comboBox1.Items" xml:space="preserve">
  <value>Car</value>
</data>
<data name="comboBox1.Items1" xml:space="preserve">
  <value>Train</value>
</data>

And it loads them like this (found in Form1.Designer.cs in Initializecomponent):

System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));

resources.ApplyResources(this.comboBox1, "comboBox1");
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Items.AddRange(new object[] {
   resources.GetString("comboBox1.Items"),
   resources.GetString("comboBox1.Items1")});
this.comboBox1.Name = "comboBox1";

It may not be exactly the answer you asked for, but being the solution that the creators of .NET came up with to the exact same problem, I suspect it would be of interest.

If you want to use the .NET/VS-native localization, just set the Language property of the form and then update all the strings via the IDE. When you switch back to (Default) your original strings will be restored. Both languages will be remembered in language-specific resx files.

Upvotes: 1

PHeiberg
PHeiberg

Reputation: 29801

You can enumerate all strings for a specific language in the ResourceManager, using the GetResourceSet method.

Upvotes: 2

Related Questions