C# application UI Text localization not working - c#

I have a context menu application where I have a base project SampleContextMenu.Base and a child project SampleContextMenu.Menu.
In SampleContextMenu.Menu, I have created a context menu for which I set a text like this.
sampleItem.Text = "Open In";
Now I want to globalize this string. So I created 3 resource files called UiStrings.resx, UiStrings.de-DE.resx, and UiStrings.fr-FR.resx.
In the class SampleContextMenu.cs, I have the following code now,
// Resource path
private string strResourcesPath = Application.StartupPath + "/Resources";
// string to store current culture which is comon in all the forms
private string strCulture = "en-US";
//resourcemanager which retrivesthe strings
//from the resource files
private static ResourceManager rm;
private void GlobalizeApp()
{
SetCulture();
SetResource();
}
private void SetCulture()
{
CultureInfo objCI = new CultureInfo(strCulture);
Thread.CurrentThread.CurrentCulture = objCI;
}
private void SetResource()
{
rm = new ResourceManager("SampleContextMenu.Menu.UiStrings", typeof(SampleContextMenu).Assembly);
}
protected override ContextMenuStrip CreateMenu()
{
// some code to create menu
strCulture = Read("language");
GlobalizeApp();
sampleItem.Text = rm.getString("0000");
}
EDIT
For me now even if the language is de or fr, it still shows stirng for the default( i.e. En)

Related

Transform Aspx to Windows Form Application

I get the link in "https://www.youtube.com/watch?v=SIs7ZsMCUWA&t=327s"
I want to change from aspx to winform
the problem:
in aspx
protected void Page_Load(object sender, EventArgs e)
{
if (Session["TokenQueue"] == null)
{
Queue<int> queueTokens = new Queue<int>();
Session["TokenQueue"] = queueTokens;
}
}
protected void btnPrinToken_Click(object sender, EventArgs e)
{
Queue<int> tokenQueue = (Queue<int>)Session["TokenQueue"];
lblStatus.Text = " Terdapat " + tokenQueue.Count.ToString() + " Antrian ";
if (Session["LastTokenNumberIssued"] == null)
{
Session["LastTokenNumberIssued"] = 0;
}
int nextTokenNumberTobeIssued = (int)Session["LastTokenNumberIssued"] + 1;
Session["LastTokenNumberIssued"] = nextTokenNumberTobeIssued;
tokenQueue.Enqueue(nextTokenNumberTobeIssued);
AddTokensToListBox(tokenQueue);
}
in c# can't read session?
Session["TokenQueue"] = queueTokens;
how to use session in c# winform?
Session normally helps us to maintain information for a user across multiple pages in a web application. When you are converting any web application to windows application you need to know the certain aspects of web application. As session is pretty common in most of web application frameworks. You can achieve same behavior by static variables in any language. In C# you can make a class to hold such information in static variables like this
internal static class SESSIONWINFORM
{
public static string TokenQueue = string.Empty;
public static DateTime LastLogin = DateTime.MinValue;
// more variables as you needed
}
Then you assign these variables values at particular events of your windows application for example in login method to save logged in time like this
protected bool login(string username, string password) {
if (succesfullLogic)
{
SESSIONWINFORM.LastLogin = DateTime.Now;
....
}
}
And to show in a Label1 to user his last login in a WinForm. You can set it text like this
Label1.Text = SESSIONWINFORM.LastLogin;
You don't need sessions since Windows apps run within the user context. There is always a single user.
I would advice to make the variable a static variable, since then it really is shared for the lifetime of the session, as it would in ASP.NET. What if you make a Session class in your Winforms project and mimic the session behavior? That would make it easier to exchange code between your projects.

What is an application adapters for hosted application in CCA?

I am new to Microsoft CRM CCA . Currently i am faceing some problems .
i created an winform and hosted it in my Agent Desktop . The winform is supposed to show the contents of a notepad in the winform's text area . How to achieve it ? I have no clue at all as there is not a much documentation on this topic . .....Plz help me out here .
here you go the complete code
using System;
using Microsoft.Uii.Csr;
namespace Microsoft.Uii.QuickStarts
{
public partial class QsHostedControl : HostedControl
{
public QsHostedControl()
{
InitializeComponent();
}
// Necessary constructor
public QsHostedControl(Guid appID, string appName, string initString)
: base(appID, appName, initString)
{
InitializeComponent();
}
private void QSHostedControl_Load(object sender, EventArgs e) {}
// This is the context change event handler.
public override void NotifyContextChange(Context context)
{
// This is the context change handler.
// Populating text fields from context information.
txtFirstName.Text = context["CustomerFirstName"];
txtLastName.Text = context["CustomerLastName"];
txtAddress.Text = context["Street"];
txtID.Text = context["CustomerID"];
// Hands control back over to the base class to notify next app of context change.
base.NotifyContextChange(context);
}
protected override void DoAction(RequestActionEventArgs args)
{
//Check the action name to see if it's something we know how to handle and perform appropriate work
switch (args.Action)
{
case "UpdateFirstName":
txtFirstName.Text = args.Data;
break;
case "UpdateLastName":
txtLastName.Text = args.Data;
break;
}
}
private void updateData_Click(object sender, EventArgs e)
{
// This is how you fire an action to other hosted applications. Your DoAction() code
// in your other application or application adapter will get called via this.
FireRequestAction(new RequestActionEventArgs("QSExternalApplication", "UpdateFirstName", txtFirstName.Text));
FireRequestAction(new RequestActionEventArgs("QSExternalApplication", "UpdateLastName", txtLastName.Text));
FireRequestAction(new RequestActionEventArgs("QSWebApplication", "UpdateFirstName", txtFirstName.Text));
FireRequestAction(new RequestActionEventArgs("QSWebApplication", "UpdateLastName", txtLastName.Text));
FireRequestAction(new RequestActionEventArgs("QSWebApplication", "UpdateAddress", txtAddress.Text));
FireRequestAction(new RequestActionEventArgs("QSWebApplication", "UpdateID", txtID.Text));
}
private void btnFireContextChange_Click(object sender, EventArgs e)
{
// Get the current context and create a new context object from it.
string temp = Context.GetContext();
Context updatedContext = new Context(temp);
// Update the new context with the changed information.
updatedContext["CustomerFirstName"] = txtFirstName.Text;
updatedContext["CustomerLastName"] = txtLastName.Text;
// Notify everyone of this new context information
FireChangeContext(new ContextEventArgs(updatedContext));
// Tell self about this change
NotifyContextChange(updatedContext);
}
}
}
you can find it in sdk also
If you wan to create an hosted application with an adapter then yoou have to use AIF(application intregation frame work) yOU CAN CHECK OUT THIS LINK hosted control
and application adapter

WPF How to get second clicked file path for Single Instance App

I created my WPF single instance app by using the Microsoft.VisualBasic dll method. However I'm facing some difficulty to get the file path for second clicked file which associated with my app.
For example, I have two file "First.my" and "Second.my". When I click on file "First.my" it will launch my app and pop up message box to show "First.my" file path. Since my app is single instance app, when I click on file "Second.my" it should show the file path for "Second.my" but it still showing the file path for "First.my"..
Does anyone know how to pass the associate file path in single instance app?
Below is my code:
class WindowsFormsApp : Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{
private App _wpfApp;
public WindowsFormsApp()
{
IsSingleInstance = true;
}
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
MessageBox.Show("First File");
//Get 1st click file path
GetFilePath();
_wpfApp = new App();
_wpfApp.Run();
return false;
}
protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e)
{
MessageBox.Show("Second File");
//Get 2nd click file path
GetFilePath();
}
protected void GetFilePath()
{
if (AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData != null &&
AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData.Length > 0)
{
var filePath = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0];
var uri = new Uri(filePath);
MessageBox.Show(uri.LocalPath);
}
}
}

Proper way to change language at runtime

What is the proper way to change Form language at runtime?
Setting all controls manually using recursion like this
Save language choice to file > Restart Application > Load languge
choice before InitializeComponent();
Using Form constructor to replace instance of active from (if this is even possible)
Something else
There is so much half written threads about this but none provides real answer on what is proper way to do this?
UPDATE:
To clarify my question:
Doing something like this:
public Form1()
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");
this.InitializeComponent();
}
works fine and all my controls and everything else in resources get translated correctly.
And doing something like:
private void button1_Click(object sender, EventArgs e)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en");
}
does nothing, Form stays in language I set up before InitializeComponent();
I believe the solution shown in Hans Passant's comment might be the only (general) solution.
Personally, I use this base class for all forms that need to be localized:
public class LocalizedForm : Form
{
/// <summary>
/// Occurs when current UI culture is changed
/// </summary>
[Browsable(true)]
[Description("Occurs when current UI culture is changed")]
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Category("Property Changed")]
public event EventHandler CultureChanged;
protected CultureInfo culture;
protected ComponentResourceManager resManager;
/// <summary>
/// Current culture of this form
/// </summary>
[Browsable(false)]
[Description("Current culture of this form")]
[EditorBrowsable(EditorBrowsableState.Never)]
public CultureInfo Culture
{
get { return this.culture; }
set
{
if (this.culture != value)
{
this.ApplyResources(this, value);
this.culture = value;
this.OnCultureChanged();
}
}
}
public LocalizedForm()
{
this.resManager = new ComponentResourceManager(this.GetType());
this.culture = CultureInfo.CurrentUICulture;
}
private void ApplyResources(Control parent, CultureInfo culture)
{
this.resManager.ApplyResources(parent, parent.Name, culture);
foreach (Control ctl in parent.Controls)
{
this.ApplyResources(ctl, culture);
}
}
protected void OnCultureChanged()
{
var temp = this.CultureChanged;
if (temp != null)
temp(this, EventArgs.Empty);
}
}
Then instead of directly changing Thread.CurrentThread.CurrentUICulture, I use this property in static manager class to change UI culture:
public static CultureInfo GlobalUICulture
{
get { return Thread.CurrentThread.CurrentUICulture; }
set
{
if (GlobalUICulture.Equals(value) == false)
{
foreach (var form in Application.OpenForms.OfType<LocalizedForm>())
{
form.Culture = value;
}
Thread.CurrentThread.CurrentUICulture = value;
}
}
}
I have found another way:
Move initialization form code in a private method like below:
private void FormInitialize() {/*Your code here*/}
In the form constructor use it like this:
public Form1()
{
InitializeComponent();
FormInitialize();
}
And from Button, menuItem or other call method like this:
private void ChangeCultureToFrench_Click(object sender, EventArgs e)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr");
this.Controls.Clear();
this.InitializeComponent();
FormInitialize();
}
I hope this helps ;-)
I've discovered this kind of approach a few minutes ago. Just quick and simple restart of the main form. Meybe it will help to someone. Event is created inside the form on my own, called when user selects the language from menu but after the selected culture's name is saved into the settings. Culture names are then loaded from that settings. Works exactly as I need and looks like proper solution.
static class Program
{
private static bool doNotExit = true;
private static FormMain fm;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
while(doNotExit)
{
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo(Properties.Settings.Default.language);//
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(Properties.Settings.Default.language);//
doNotExit = false;
fm = new FormMain();
fm.lanugageChangedEvent += new EventHandler(main_LanugageChangedEvent);
Application.Run(fm);
}
}
static void main_LanugageChangedEvent(object sender, EventArgs e)
{
doNotExit = true;
fm.Close();
}
}
In reference to your ColumnHeader .NET framework bug, I also discovered this bug recently and posted a question about it (to which I haven't received any responses). I was able to fix the problem by hardcoding the changes for the ColumnHeaders. For example:
resources.ApplyResources(_myHeader, "_myHeader", culture);
You basically just replace the call to .Name with a literal string of the name. I have tested this and it works. Unfortunately this means it won't fit as part of the code you use to change all of the controls. You will have to add a line for each ColumnHeader object you need to change. If you have a listview with a variable number of columns, that could get tricky. Another option is to create localized resource files. I assume you probably already have them for stuff like message box text and other strings. Then you can add an entry in your resource file like "columnHeader_myHeader" and set the appropriate language text for each language. Finally, you can manually change the text to your column headers by using:
_myHeader.Text = myResourceFileName.columnHeader_myHeader;
This will select the appropriate language based on the current thread culture.
Hans was correct in that there doesn't seem to be a foolproof "proper" way to perform localization in .NET, though there are a variety of tools you can use. For something like a job application, even though it is probably already too late for this advice, my suggestion would be to learn as many different methods as you can for localization, learn the pros and cons, and then just pick a system and be able to argue why you believe it is the "proper" choice. They are probably more concerned with your logic and reasoning and demonstration of prior experience than they are with the actual method.
Hope this would help anyone, I found it best for me cause i needed to change buttons location according the lang (browse on the right or left of the search box and labels next to text fields).
save a public var on the main that will hold the lang.
created a class which handles the visual part
created xml files that will hold any language data and more (in my xml tag name=object name).
sent that class's constructor the form (to save and work with)
connect to that current xml file
From main form call whenever you want to initialView (part of the view class) and change lang (and more) anytime (just connect to the right xml file):
public void initialView()
{
//Set rightToLeft values
initialIndent(mainForm);
//set visual text values
initialTxt();
}
private void initialTxt()
{
// Are there any more controls under mainObj (Form1)?
Boolean endOfElemsUnderPnl = false;
// The current Control im working on
Object curObj = mainForm;
do
{
// MenuStrip needs to be handled separately
if (typeof(MenuStrip).ToString().Equals(curObj.GetType().ToString()))
{
foreach (ToolStripMenuItem miBase in ((MenuStrip)(curObj)).Items)
{
miBase.Text = mainForm.dbCon.getData(miBase.Name.ToString());
foreach (ToolStripMenuItem miInnerNode in miBase.DropDownItems)
{
miInnerNode.Text = mainForm.dbCon.getData(miInnerNode.Name.ToString());
}
}
}
// Any other Control i have on the form
else
{
((Control)(curObj)).Text = mainForm.dbCon.getData(((Control)(curObj)).Name.ToString());
}
curObj = mainForm.GetNextControl(((Control)(curObj)), true);
// Are there any more controls under mainObj?
if (null == curObj)
{
endOfElemsUnderPnl = true;
}
} while (!endOfElemsUnderPnl);
}
private void initialIndent(frmMyFileManager parent)
{
if (parent.Language.Equals("Hebrew"))
{
parent.RightToLeft = RightToLeft.Yes;
}
else if (parent.Language.Equals("English"))
{
parent.RightToLeft = RightToLeft.No;
}
else
{
parent.RightToLeft = RightToLeft.No;
}
}
And this is an example of how easy it is for my at runtime:
private void selectLanguageToolStripMenuItem_Click(object sender, EventArgs e)
{
DialogResult res = MessageBox.Show(this, "click yes for english and no for hebrew", "Select language", MessageBoxButtons.YesNoCancel);
if (DialogResult.Yes == res)
{
Language = "English";
}
else if (DialogResult.No == res)
{
Language = "Hebrew";
}
dbCon = new CDBConnector("****\\lang" + Language + ".xml");
view.initialView();
}

Create a customized path address (wpf)

Goal:
I want to achieve the path address, as string, of the application created in Visual studio 2010. The path is from unit (c or d unit) to the name of the application.
Problem:
I can't create a customized path address in runtime. I don't want a full path address that is from unit to the name of the picture.
--No to this path address
"D:\work\Modul3\Assignment3\Assignment3\bin\Debug\logotyp_vp_final.jpg"
--Yes, requested path
"D:\work\Modul3\Assignment3"
Please remember that this application and its name of the application and the address can be changed from time to time.
namespace Assignment3
{
/// <summary>
/// Interaction logic for FlightForm.xaml
/// </summary>
public partial class FlightForm : Window
{
public delegate void TakeOffHandler(object source, TakeOffEventArgs e);
public delegate void ChangeHandler(object source, ChangeRouteEventArgs e);
public event TakeOffHandler TakeOffEvent;
public event ChangeHandler ChangeEvent;
public FlightForm()
{
InitializeComponent();
Title = "Flight ";
cmbStatus.Visibility = Visibility.Hidden;
btnLand.Visibility = Visibility.Hidden;
string fullPath;
fullPath = System.IO.Path.GetFullPath("logotyp_vp_final.jpg");
BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(fullPath);
image.EndInit();
image1.Source = image;
System.Windows.Shapes.Path path = new System.Windows.Shapes.Path();
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
cmbStatus.Visibility = Visibility.Visible;
btnLand.Visibility = Visibility.Visible;
btnStart.Visibility = Visibility.Hidden;
TakeOffEvent(this, new TakeOffEventArgs("a", "b", DateTime.Now.ToString()));
ChangeEvent(this, new ChangeRouteEventArgs("aa", "bb", "cc"));
}
}
}
namespace Assignment3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class ControlTower : Window
{
public ControlTower()
{
InitializeComponent();
}
private FlightForm myFlightForm;
private void btnSendNextAirplane_Click(object sender, RoutedEventArgs e)
{
myFlightForm = new FlightForm();
myFlightForm.TakeOffEvent += new FlightForm.TakeOffHandler(PrintOutTakeOff);
myFlightForm.ChangeEvent += new FlightForm.ChangeHandler(PrintOutChange);
myFlightForm.Show();
}
public void PrintOutTakeOff(object source, TakeOffEventArgs e)
{
lstDisplay.Items.Add(new { FlightCode = e.FlightCode, Status = e.Status, Time = e.Time });
}
public void PrintOutChange(object source, ChangeRouteEventArgs e)
{
string test = e.FlightCode + e.Status + e.Time;
MessageBox.Show(test);
}
}
}
To get the path of where the application is executing from:
string localPath = new Uri( Assembly.GetExecutingAssembly().CodeBase ).LocalPath;
string currentDirectory = Path.GetDirectoryName( localPath );
edit
It sounds like you are attempting to access images outside of your project. As this may work in your sandbox environment, a better practice is to include the images as a part of your project and access them as an embedded resource.
Here's a good read to get you started: Adding and Editing Resources (Visual C#)
Walk-through of adding an image as an embedded resource
Add the file to your project, typically something along the lines of:
+solution
+project
+Resources <-- this is Visual Studio's default folder name for resources
+SomeDirectory
-logotyp_vp_final.jpg
Then:
go to your project's properties
click to the resources tab on the left side
select the images resource on the top nav bar.
select to add a resource > add existing file. Browse to the file you just put into your project and select to add it.
The file will now show up under your Resources tab of your project's properties. Change the name of your file in the Resources tab to be more meaningful.
Now that the file is an embedded resource of your project, you can access it by the following in code:
var MyFile = Properties.Resources.logotyp_vp_final
Something like this should work:
var fullPath = System.IO.Path.GetFullPath("..\\..\\logotyp_vp_final.jpg");

Categories

Resources