I've been developing a c# app. (It runs OK, there's not problem).
But Now, my boss need it work on English, Spanish and other languages.
I saw some tutorials about how to change languages in my app on different web pages (like this, and this)
My problem is:
I don't have defined any item, I mean, I don't have text boxes, labels or buttons. I just have a form:
While my app is running, it reads a .txt file: If there's a "button" line in the .txt, my app will add a button to my form, if there's a "label" line, it will add a new label.
So, I can't use the .resx file as the tutorials said.
It doesn't work.
I donĀ“t know if I'm doing it wrong or it simply doesn't work
Any idea?
I don't know what to do
I read the. txt file (line by line) and I assign the properties like this
public static Label[] LAB = new Label[2560];
public static int indice_LABEL = 0;
if (TipoElemento == "LABEL")
{
LAB[indice_LABEL] = new Label();
LAB[indice_LABEL].Name = asigna.nombreElemento;
LAB[indice_LABEL].Left = Convert.ToInt32(asigna.left);//LEFT
LAB[indice_LABEL].Top = Convert.ToInt32(asigna.top);//TOP
LAB[indice_LABEL].Width = Convert.ToInt32(asigna.width);
LAB[indice_LABEL].Height = Convert.ToInt32(asigna.height);
//and all I need
...
...
Formulario.PanelGE.Controls.Add(Herramientas.LAB[Herramientas.indice_LABEL]);
Herramientas.indice_LABEL++;
}
If you need to stick with this format, the best solution would be to have 1 file with all the control definitions (name, dimensions, position etc) and another with the text to display to the user
Then when you create each control, instead of assigning it a caption you use the ResourceManager, linked to your 'captions' files (1 for each language) to retrieve the correct string to display
For example:
Language Text File
This will be a simple text file, resource.en-US.txt
Inside, you will need to add simple key>value pairs:
label1=Hello world!
To make another language, simply create another file, resource.fr-FR.txt, and add:
label1=Bonjour le monde!
Application Code
// Resource path
private string strResourcesPath= Application.StartupPath + "/Resources";
// String to store current culture which is common in all the forms
// This is the default startup value
private string strCulture= "en-US";
// ResourceManager which retrieves the strings
// from the resource files
private static ResourceManager rm;
// This allows you to access the ResourceManager from any form
public static ResourceManager RM
{
get
{
return rm ;
}
}
private void GlobalizeApp()
{
SetCulture();
SetResource();
SetUIChanges();
}
private void SetCulture()
{
// This will change the current culture
// This way you can update it without restarting your app (eg via combobox)
CultureInfo objCI = new CultureInfo(strCulture);
Thread.CurrentThread.CurrentCulture = objCI;
Thread.CurrentThread.CurrentUICulture = objCI;
}
private void SetResource()
{
// This sets the correct language file to use
rm = ResourceManager.CreateFileBasedResourceManager
("resource", strResourcesPath, null);
}
private void SetUIChanges()
{
// This is where you update all of the captions
// eg:
label1.Text=rm.GetString("label1");
}
Then all you need to do is change the private string strCulture= "en-US" to "fr-FR" (eg in a combo box), and call the GlobalizeApp() method, and the text in label1 will change from Hello world to Bonjour le monde!
Simple (I hope :) )
Check out this link for a great walkthrough
Related
I have a DropDown (using MahApps if that is important) that I'd like to use to switch the language "on the fly" in my program.
Language Class
namespace SAM
{
public class Language
{
public string Title { get; set; }
public string Culture { get; set; }
}
}
Change Language
private void DropLanguage_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
Language lang = DropLanguage.SelectedItem as Language;
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang.Culture);
}
I have all my strings as resources in Resources.resx (default) and Resources.en.resx (english)
3 issues I don't understand
When selecting "englisch" from the dropdown, the language does not change immediately but when I click sth. else, e.g. "close" (it asks "sure?"), the language has changed.
Strings that are directly in the .xaml file like <TextBlock Text="{x:Static p:Resources.Config_HeaderBar_Find_Speaker}" /> do not get updated at all.
Bonus: How would I switch back to the default language, as new CultureInfo(lang.Culture); expects one parameter and for the default I have Culture = null (as the Resources.resx has nothing in it's name). Changing the file to Resources.default.resx messes with my code a lot...
I tried to solve similar problem. The simplest solution for me was to move all Window content to UserControl and creating interface for window with method refreshLanguage(). Then I call from model:
private void SetLanguage(string cultureName)
{
var cul = new System.Globalization.CultureInfo(cultureName);
Properties.Resources.Culture = cul;
System.Globalization.CultureInfo.DefaultThreadCurrentCulture = cul;
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = cul;
System.Threading.Thread.CurrentThread.CurrentUICulture = cul;
System.Threading.Thread.CurrentThread.CurrentCulture = cul;
InitializeHamburgerMenu();
MainWindowView.RegreshLanguage();
RaisePropertyChanged("Title");
}
And RefreshLanguage in Window looks like:
public void RegreshLanguage()
{
GlobalUserControl content = new GlobalUserControl("Views/SettingsPage.xaml");
ContentPresenter_GlobalUserControl.Content = content;
}
In my case, UserControl provides navigation, so I passed last navigated URI as parameter. So, if you need to preserve state you can pass it as parameter to new UserControl. Recreating usercontrol cause all strings to reload without window recreation. Maybe good idea would be to call GC.Collect(); here, but depends on your scenario.
About default neutral culture. For me works to call SetLanguage("").
There are 2 things
Thread.CurrentThread.CurrentCulture
and
Thread.CurrentThread.CurrentUICulture
In order to set these valuse use the static method
CultureInfo.GetCultureInfo(String langCode)
where some examples of the parameter langCode are the following strings
"de-DE"
"en-US"
etc.
more info at
https://msdn.microsoft.com/en-us/library/yck8b540(v=vs.110).aspx
So, overall these lines of code sould work for change in German Language:
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("de-DE");
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("de-DE");
I'm attempting to find a document on my window that has a rich text box with text in it using TestStack White, and extract that text.
I've tried to use the UIItem Label & TextBox, but White doesn't seem to be able to find the object during my test. The object can be found using the generic UIItem, but I want to be able to access the text it holds.
I'm implementing it like:
public [Unsure] MyRichTextBox
{
get { return Window.Get<[Unsure]>(SearchCriteria.ByClassName("RichTextBox")); }
}
and I'd like to be able to say:
Assert.That(MyRichTextBox.Text.Equals(x));
But it can't find what I'm looking for if I tag it as a Label or a TextBox, and I don't have access to .Text if I declare it a UIItem.
You want to use the type of TextBox. Then you can use BulkText to access the text in the RichEditBox.
First the Window:
TestStack.White.UIItems.WindowItems.Window _mainWindow;
app = TestStack.White.Application.Launch(startInfo);
_mainWindow = app.GetWindow("MyDialog");
Then Find the richEditBox:
public string _richeditdocument_ID = "rtbDocument";
private TextBox _richeditdocument_ = null;
public TextBox RichEditDocument
{
get
{
if (null == _richeditdocument_)
_richeditdocument_ = _mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId(_richeditdocument_ID));
return _richeditdocument_;
}
}
Then use the following to access the text:
string data = RichEditDocument.BulkText;
Here are the code comments for using the Text Method in White:
// Summary:
// Enters the text in the textbox. The text would be cleared first. This is
// not as good performing as the BulkText method. This does raise all keyboard
// events - that means that your string will consist of letters that match the
// letters of your string but in current input language.
public virtual string Text { get; set; }
Here are the comments for using BulkText:
// Summary:
// Sets the text in the textbox. The text would be cleared first. This is a
// better performing than the Text method. This doesn't raise all keyboard events.
// The string will be set exactly as it is in your code.
Take a look on the code ,i hope you will understand what I'm trying to do:
private void btnOpen_Click(object sender, EventArgs e)
{
string[] Folders = Directory.GetDirectories(txtFolder.Text);
string foldername;
int count=0;
foreach (string f in Folders)
{
foldername = Path.GetDirectoryName(f);
Label newlabe = new Label();
newlabe.Location = new Point(12, 58);
newlabe.Text = foldername;
count++;
}
}
as you can see i insert a Directory Path into text box , then I opened an array which contains the sub Directories,the next step is to open labels which contains the sub directories names from the directory i insert to the text box, that's not working , what should i do ?
Use some kind of container and stack/add the labels into it. You don't need to assign a location to the label, as the container (depending on the container layout algorithm) will layout them for you.
I dont know whether you use WinForms or WPF or something else, so I will not write any sample code.
But here is some pseudocode:
create a container and add it to the form
for each folder
create a label for the folder
add the label to the container
by the way, have you tried a TreeView control?
I have a window based application in C#. I am trying to do this for some another language, say arabic.
As we know there is resource file for each form. I have created a global resource file as ResouceFileName.ar-SA.resx . Now I want to change all labels dynamically when I change CultureInfo. If i write in designer file like
static class clsLocalization
{
static ResourceManager resManager = new ResourceManager(typeof(Secure_Browser_CS_Version.Properties.Resources));
public static void applyGlobalResources(Control control,string resource)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("ar-SA");
control.Text=resManager.GetString(resource);
}
}
// Resource file
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SBMainForm));//Default
//
// settingHdrLbl
//
resources.ApplyResources(this.settingHdrLbl, "settingHdrLbl");
clsLocalization.applyGlobalResources(this.settingHdrLbl, "settingHdrLbl");
this.settingHdrLbl.BackColor = System.Drawing.Color.Transparent;
this.settingHdrLbl.Name = "settingHdrLbl";
This will be reload as default whenever i change in designer file. Pl help me out
I am in need of some guidance for the following design.
I have a tab control that contains various group boxes. Within the group box, there are specific controls that relates to that group box. For example:
Now whenever a change is made to any control in the group box, the value for the control needs to be tracked because at the end of the application run cycle, the control data will need to be saved to a file that contains that value. An example file is:
HOT_STANDBY_FEATURE_ENABLE [val from control here]
HEART_BEAT_DIGITAL_OUTPUT [val from control here]
....
A design that I have in mind has another that has just properties that the group box form sets whenever a ValueChanged event occurs on a control.
Example code:
class ConfigurationValues
{
public int HotStandbyValue { get; set; }
public int HeartBeatDigitalOutputValue { get; set; }
//...add all other controls here
}
The downside that I see to this is that there are 40 controls on that tab page, so I'd have to manually type each property. When the file needs to be generated at the end of the application run cycle, I have a method that gets the value of the control need.
Example:
private void GenerateFile()
{
string[] file =
"HOT_STANDBY_FEATURE_ENABLE " + ConfigurationTabSettings.HotStandbyValue;
}
Another design consideration I need to make is that whenever a user clicks "Open Configuration File", the values from the file from disk need to be loaded into the properties so the form can take that data on startup and populate the controls within the group boxes with their respective values.
Any suggestions on this design would be greatly appreciated. I know this is not the most efficent way to do this and am not the most experienced programmer, so any Google keywords I can search for would be great also.
You could xml serialise and xml deserialise your ConfigurationValues class rather than writing manual "generate file" and "read file" methods
http://support.microsoft.com/kb/815813
You'll need to bind the controls Text or Value properties to the properties in your ConfigurationValues class e.g.
ConfigurationValues cv = Repository.ReadConfigValues();
numPulseFilterDelay.DataBindings.Add("Value", cv, "PulseFilterDelay");
// Add the rest of your control bindings here
on the btnSave_Click() of your Form, end the current edit on the form and save the config values
void btnSave_Click(object sender, EventArgs e)
{
BindingContext[cv].EndCurrentEdit(); // Commits all values to the underlying data source
Repository.SaveConfigValues(cv);
}
In your repository class you'll need methods to Load() and Save() the data. You can put XmlSerialization code in here, or write your own format (depending on your requirements)
public class Repository
{
public static ConfigurationValues LoadConfigValues()
{
var cv = new ConfigurationValues();
string[] lines = File.ReadAllLines("values.cfg");
foreach (string cfg in lines)
{
string[] nameValue = cfg.Split(new char[] { ' ' } ); // To get label/value
if (nameValue[0] == "HOT_STANDBY_FEATURE_ENABLE")
cv.HotStandbyFeatureEnable = nameValue[1];
else if (nameValue[0] == "SOME_OTHER_PROPERTY")
cv.SomeOtherProperty = nameValue[2];
// Continue for all properties
}
return cv;
}
public static void SaveConfigValues(ConfigurationValues cv)
{
var builder = new StringBuilder();
builder.AppendFormat("HOST_STANDBY_FEATURE_ENABLE {0}\r\n", cv.HostStandbyFeatureEnable);
// Add the rest of your properties
File.WriteAllText("values.cfg", builder.ToString());
}
}