C# Windows Phone 8.1 Language selection - c#

I hope this wasn't asked before, I couldn't find an easy solution in MSDN or here.
The windows phone 8.1 application is deployed in more than one language.
To do so I use the default language (english) in Strings\en-US\Ressources.resw and installed the Multilingual App Toolkit with all further languages added there.
To change the language, I have the following code:
private void changeLang(string cul)
{
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = cul;
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
if (Frame != null)
Frame.Navigate(typeof(MainPage));
}
which can be called by
changeLang("en-US");
After that I have to restart the application (couldn't make it work without restart yet).
The problem is my implementation. I created a page called Settings where I want to provide the user the possibility to change the language.
Now I want to provide the user a ComboBox with all the languages I have translated. By default the selected ComboBoxItem should show the current language of the application (not the Systems language, as the user might already have had changed the language).
Here my solution to the problem, I hope this might be useful to others as well.
First we create a new struct:
public class ComboboxItem
{
public string Text { get; set; }
public object Value { get; set; }
public override string ToString()
{
return Text;
}
}
Then on the OnNavigate part on the Form we add the following code:
settings_language_cb.Items.Add(new ComboboxItem { Text = "Deutsch", Value = "de-DE" });
settings_language_cb.Items.Add(new ComboboxItem { Text = "English", Value = "en-US" });
var curLangItem = settings_language_cb.Items.SingleOrDefault(x => (x as ComboboxItem).Value.ToString() == CultureInfo.CurrentCulture.Name);
settings_language_cb.SelectedItem = curLangItem;
settings_language_cb.PlaceholderText = (curLangItem as ComboboxItem).Text;
And that's all.

You can try something like this
class LanguageCode
{
string Name { get; set; },
string CodeName { get; set; }
}
var langs = new List<LanguageCode>();
langs.Add(new LanguageCode() { Name = "English", CodeName = "en-US" });
langs.Add(new LanguageCode() { Name = "Deutsch", CodeName = "de-DE" });
// ... and so on ...
settings_language_cb.Items.Add(langs);
settings_language_cb.SelectedIndex = 0;
On the ComboBox, change the code to:
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var si = settings_language_cb.SelectedItem as LanguageCode;
if(si != null)
changeLang(si.CodeName); // changeLang("de-DE");
}

#MrEko
it's easy to get the selected item.
First you have to create a SelectionChanged event in your XAML Combobox and then you will get the selected item as following:
(myXAMLComboBox.SelectedItem as ComboboxItem).Value.ToString();
and here the whole thing in action. (note that oldLang is a constant that I save when I change the language and changeLang is the function that changes the language). And of cause, after changing the language, you have to restart your App, so it takes effect.
private void Page_Settings_LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (oldLang != (PageSettings_Language_cb.SelectedItem as ComboboxItem).Value.ToString())
{
try
{
changeLang((PageSettings_Language_cb.SelectedItem as ComboboxItem).Value.ToString());
ShowRestartMessageBox();
}
catch (Exception)
{ }
}
}

Related

Need help populating Listbox with json, currently displaying empty values

im completly new to programing,
im trying to create something like a manga organizing tool in windows forms, but im getting stuck in populating a listbox with data from a deserialized json string, it currently is only displaying boolean values correctly all other values are "0" even strings.
i have a button to do this:
using (OpenFileDialog openFileDialog = new OpenFileDialog() { Filter = "Json Files|*.json", ValidateNames = true, Multiselect = false })
{
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
var fileStream = openFileDialog.OpenFile();
using (StreamReader sr = new StreamReader(fileStream))
{
string fileContent = sr.ReadToEnd();
ComicList comics = JsonConvert.DeserializeObject<ComicList>(fileContent);
Manga_listBox.DataSource = DisplayComic.FullList;
//ignore this little bit it's just so i can see what's happening
label1.Text = Convert.ToString(comics.Comics.Count);
label1.Text = Convert.ToString(DisplayComic.FullList);
}
}
}
and i have the following classes like so:
public class Comic
{
private string Manga;
private int Chapters;
private bool isFinished;
private int LastReadCH;
public string Manga1 { get => Manga; set => Manga = value; }
public int Chapters1 { get => Chapters; set => Chapters = value; }
public bool IsFinished { get => isFinished; set => isFinished = value; }
public int LastReadCH1 { get => LastReadCH; set => LastReadCH = value; }
public Comic(Comic asd)
{
this.Manga = Manga1;
this.Chapters = Chapters1;
this.IsFinished = IsFinished;
this.LastReadCH = LastReadCH1;
}
public override string ToString()
{
return string.Format("{0}, {1}, {2}, {3}",
this.Manga, this.Chapters, this.IsFinished, this.LastReadCH);
}
}
and
public class ComicList
{
private List<Comic> comics;
public List<Comic> Comics { get => comics; set => comics = value; }
}
and
public class DisplayComic
{
static DisplayComic()
{
using (OpenFileDialog openFileDialog = new OpenFileDialog() { Filter = "Json Files|*.json", ValidateNames = true, Multiselect = false })
{
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
var fileStream = openFileDialog.OpenFile();
using (StreamReader sr = new StreamReader(fileStream))
{
string fileContent = sr.ReadToEnd();
ComicList comics = JsonConvert.DeserializeObject<ComicList>(fileContent);
FullList = comics.Comics;
}
}
}
}
private static List<Comic> fullList;
public static List<Comic> FullList { get => fullList; set => fullList = value; }
public static List<Comic> GetComcis()
{
return FullList;
}
}
code is probably quite messy, then again I'm completely new and have been following all kind of information online, also for some reason, the open dialog windows is opening twice I don't understand why.
here is the json file I'm using:
{
"Comics": [
{
"Manga": "MangaNumber1",
"Chapters": 85,
"isFinished": true,
"LastReadCH": 85
},
{
"Manga": "MangaNumber2",
"Chapters": 112,
"isFinished": true,
"LastReadCH": 112
},
{
"Manga": "MangaNumber3",
"Chapters": 117,
"isFinished": true,
"LastReadCH": 117
},
{
"Manga": "MangaNumber4",
"Chapters": 74,
"isFinished": true,
"LastReadCH": 74
}
]
}
I've tried pretty much anyone with my "expertise" could, changing all kind of variable names and so on, would really appreciate some help.
here's a screenshot of the problem:
as you can see only the boolean values are actually correct, otherwise they'd be false, all other values though...
EDIT:
the result im hopping for is to populate the listbox with the manga names, (thank you #beeker for that property thing) and once i select said manga then i want to create some other objects such as labels and text boxes to view and edit the values of the chapters etc, also i would like to be able to see what is being parsed by the json file how ever when i do this:
label1.Text = Convert.ToString(comics);
i get the label with the text "Manga_Organizer_2.ComicList"
By the way when i say im new, i mean i only ever did stuff with console apps using only "if" functions this whole parsing json, openfiledialog, and even classes usage is completly new. I also have no background in programing with any other language c# is the first and im loving it even though having terrible difficulties :)
Answer/Update:
All is good now :)
all i had to do was set
DisplayComic.FullList = comics.Comics;
in the openfiledialog right before setting the datasource for the listbox.
In the end it looks like this:
string fileContent = sr.ReadToEnd();
ComicList comics = JsonConvert.DeserializeObject<ComicList>(fileContent);
DisplayComic.FullList = comics.Comics;
Manga_listBox.DataSource = DisplayComic.FullList;
Manga_listBox.DisplayMember = "manga";
also removed the encapsulations alltogether in the comic class, in the end it looks like this:
public class Comic
{
public string Manga { get; set; }
public double Chapters { get; set; }
public bool IsFinished { get; set; }
public double LastReadCH { get; set; }
public string StartedOn { get; set; }
public string FinishedOn { get; set; }
}
and also the displaycomic class looks like this:
public class DisplayComic
{
public static List<Comic> FullList { get; set; }
public static List<Comic> GetComcis()
{
return FullList;
}
}
Also, after all this trouble came even more, i could deserialize the json, parse it to a string and then to a list, load, save and edit it and i also managed to serialize it back together, and with a savefiledialog create a file for it, however when i did, i would be unable to re-deserialize it once again, something about the json had changed (from object to array or vice versa), aside from that i also had problems with datetime stuff, couldn't load it correctly from a string and so on, anyway after a bunch of mishaps, and litteraly 17hours of looking at code with a puzzled face i finnaly finished my app :D!
It does all i want it to, load a json, save and edit it, put it back together, add and remove from it, and i learned a bunch from all this trouble, thank you all for helping, thanks to you guys learned how to set stuff to display on listboxes, and also very importantly "somewhat" learned how to debug code.
Thanks.
Try setting the listbox "DisplayMember" property so that the control knows which property of the class you want to see. Something like this...
Manga_listBox.DataSource = DisplayComic.FullList;
Manga_listBox.DisplayMember = "Manga";
Ref:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.listcontrol.displaymember?view=netframework-4.8
Answer:
i removed that whole openfiledialog in the display comic class, renamed the encapsulations in the Comic class and done :D, now the openfiledialog only opens once and the values from the json are being correctly parsed to the comics list, thus enabling me to use them however i want, thank you, you pushed me in the right direction with the idea to learn debug stuff :D.
Now all that's left is learn how to create objects by selecting the different lines from the listbox, another challenge awaits this newcomer.

Filtering ListBox using combobox and LINQ

I have a winform that includes a ListBox and a Combobox. In this ListBox appears a clients list on first run.
I want to filter the "Clients" in the ListBox with a Combobox.
To fill the ListBox using the string selected in the Combobox i'm using :
private void FillListBox()
{
this.lstClient.Items.Clear();
foreach (Client c in this.client)
{
if (this.cBox.Text == "All")
this.lstClient.Items.Add(c.ToString());
else
if (this.cBox.Text == "Retail" && c.GetType() == typeof(RetailClient))
this.lstClient.Items.Add(c.ToString());
}
this.lstClient.Sorted = true;
}
After that i call this method from the event of the ComboBox :
private void cBox_TextChanged(object sender, EventArgs e)
{
this.FillListBox();
}
It works "great" but my code is not really dynamic and too long (lots of differents clients) that's why i would like to use LINQ.
I read on microsoft's documentation but i'm pretty confused on how using it.
Does anyone have some times to show me the way ?
Adding infos :
My form :
I select the type i want in the ComboBox :
The result :
Thanks
Ok let's give it a try. If you want to implement filtering you should think about a proper structure how to represent your filter criterion. In this case you have a label in your combobox which is bound to a unique filter criterion. This could be represented by a custom class:
public class SortingRepresentation
{
public string DisplayLabel { get; set; }
public Type ClientType { get; set; }
}
Now you can create a List of those criteria and shove it into the combobox:
List<SortingRepresentation> sortingFields = new List<SortingRepresentation>();
public Form1()
{
sortingFields.Add(new SortingRepresentation{ DisplayLabel = "All", TypeCriterion = typeof(Client) });
sortingFields.Add(new SortingRepresentation{ DisplayLabel = "Only Retail", TypeCriterion = typeof(Client_A) });
sortingFields.Add(new SortingRepresentation{ DisplayLabel = "Only Wholesale", TypeCriterion = typeof(Client_B) });
sortingFields.Add(new SortingRepresentation{ DisplayLabel = "Only Human Wholesale", TypeCriterion = typeof(Client_C) });
cBox.DisplayMember = "DisplayLabel";
cBox.DataSource = sortingFields;
}
When the selection changes in the combobox you can catch now the selected item (which will be of type SortingRepresentation and pass it as a filter to FillListBox:
private void cBox_SelectedIndexChanged(object sender, EventArgs e)
{
FillListBox((SortingRepresentation)cBox.SelectedItem);
}
Now you can use the Type TypeCriterion inside this object to filter your list:
private void FillListBox(SortingRepresentation sortcriterion)
{
this.lstClient.DataSource = null;
this.lstClient.DataSource = client
.Where(x => x.GetType() == sortcriterion.TypeCriterion || // either you are of this type
x.GetType().BaseType == sortcriterion.TypeCriterion // or your parent is of this type
).ToList();
}
Since you are using a listbox, you can bind the sorted list directly to the DataSource and be done with it. For the proper display, you need to override the ToString method in your Client class and the ListBox will take care of the display accordingly. But as I see you've done it already

NSTextField with suggestions shown in dropdown

I am trying to implement autocomplete with an NSTextField where the user will type in some string and suggestions will be fetched from an API to be displayed under the text field. Optionally display a progress indicator inside the text field. So far I have designed the UI in Xcode IB and hooked the event to get the text change event.
public class UserTextFieldDelegate: NSTextFieldDelegate
{
public NSTextField Username { get; set; }
public UserTextFieldDelegate()
{
}
public UserTextFieldDelegate(NSTextField username)
{
this.Username = username;
}
public override void Changed(NSNotification notification)
{
Console.WriteLine(Username.StringValue);
}
}
The API will return a list of objects which I need to bind with the datasource of autocomplete list.
How do I achieve this in Xamarin.Mac?
In the NSTextField.Changed, save the NSTextView from the NSNotification parameter and call your Rest API:
NSString NSFieldEditor = new NSString("NSFieldEditor");
NSTextView editor;
[Export("controlTextDidChange:")]
public void Changed(NSNotification notification)
{
editor = editor ?? notification.UserInfo.ObjectForKey(NSFieldEditor) as NSTextView;
SomeRestCall(nsTextField.StringValue);
}
Now with your Rest method, call the actual Rest api via a background queue and save/buffer the completion words returned in a string array and then call NSTextView.Complete on the NSTextView instance variable that you saved from the Changed method:
string[] completionWords = { };
void SomeRestCall(string search)
{
if (editor != null)
{
DispatchQueue.GetGlobalQueue(DispatchQueuePriority.Background).DispatchAsync(() =>
{
if (string.IsNullOrWhiteSpace(search))
completionWords = new string[] { };
else
// Fake a REST call...
completionWords = (new string[] { "sushi", "stack", "over", "flow" })
.Where((word) => word.StartsWith(search, StringComparison.CurrentCulture)).ToArray();
if (editor != null)
DispatchQueue.MainQueue.DispatchAsync(() => { editor?.Complete(null); });
});
}
}
In your implementation of INSTextFieldDelegate add the GetCompletions protocol and return completion words that you saved in the last step:
[Export("control:textView:completions:forPartialWordRange:indexOfSelectedItem:")]
public string[] GetCompletions(NSControl control, NSTextView textView, string[] words, NSRange charRange, ref nint index)
{
requestor = null;
return completionWords;
`}

onClick fetch data c# xml reader

I am trying to have a button that on button1_click it opens an URL to fetch live exchange rates. i am a little unsure where to actually place the algorithm. so for this purpose can we assume its a blank windows form with a single button that upon clicking prints the fetched data next to the clicked button.This is what i have keep in mind im new to c# and visual studio changed a few things that made my initial code much more confusing to me any simplification helps.
public partial class eth: Form
{
private const string InputUri = #"https://api.bitfinex.com/v1/ticker/ethusd";
public eth()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
public static List<KeyValuePair<string, decimal>> GetCurrencyListFromWeb(out DateTime currencyDate)
{
List<KeyValuePair<string, decimal>> returnList = new List<KeyValuePair<string, decimal>>();
string date = string.Empty;
currencyDate = NewMethod(returnList, ref date);
returnList.Add(new KeyValuePair<string, decimal>("usd", 1));
return returnList;
}
}
private static DateTime NewMethod(List<KeyValuePair<string, decimal>> returnList, ref string date)
{
DateTime currencyDate;
using (XmlReader xmlr = XmlReader.Create(InputUri))
{
xmlr.ReadToFollowing("bid");
while (xmlr.Read())
{
if (xmlr.NodeType != XmlNodeType.Element) continue;
if (xmlr.GetAttribute("timestamp") != null)
{
date = xmlr.GetAttribute("timestamp");
}
else returnList.Add(new KeyValuePair<string, decimal>(xmlr.GetAttribute("ask"), decimal.Parse(xmlr.GetAttribute("last_price"), CultureInfo.InvariantCulture)));
}
currencyDate = DateTime.Parse(date);
}
return currencyDate;
}
}
}
The below code is tested and working fine. You are calling a REST endpoint and it is returning a list of values as a json. I am using the HttpClient to call the endpoint and will need to add the other properties as needed from the documentation. One thing to be mindful is that the results change with the symbols provided. So, will need to provide that responsibility to another class. In fact, you should always move the external library calling to another class to comply with the SRP.
public partial class ExchangeRates : Form
{
public ExchangeRates()
{
InitializeComponent();
}
private const string InputUri = #"https://api.bitfinex.com/v1/ticker/ethusd";
private async void button1_Click(object sender, EventArgs e)
{
var result = await GetTicker();
richTextBox1.AppendText($"mid: {result.Mid}\n");
richTextBox1.AppendText($"bid: {result.Bid}\n");
richTextBox1.AppendText($"ask: {result.Ask}");
}
private static async Task<Ticker> GetTicker()
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(InputUri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var output = JsonConvert.DeserializeObject<Ticker>(content);
return output;
}
throw new Exception("Ticker exception.");
}
}
public class Ticker
{
[DataMember(Name = "mid")]
public decimal Mid { get; set; }
[DataMember(Name = "bid")]
public decimal Bid { get; set; }
[DataMember(Name = "ask")]
public decimal Ask { get; set; }
// other properties
}
Update 1
Sorry about the issue. I have used Newtonsoft.Json package here. We can use string manipulation also but it is a bit ugly. So, use the JArray from the package to convert the result to an array.
Update 2
Ok, I scrapped the JArray part and went back to string splits.
Update 3
Really sorry, I have used a different end point earlier. I have updated answer according to the required end point. Here you will have to use the JsonConvert class from the same Newtonsoft.Json package. I have also added DataMember attributes for easy deserialization. DataMember is part of System.Runtime.Serialization namespace.
Update 4
Appended the results to a rich text box as you have requested. But, why do want them in a rich text box? These are read only data that you want to display to the users. I believe you should have different labels for each field and display them separately.

How create a dynamic DataAnnotations Attribute for validation on MVC5 (globalization)?

I'm using ef6 with mvc5.
My project need multiple language. So I need create a DataAnnotations Attribute for validation these field.
For example: I have a Id property:
public int Id { get; set; }
For validation I need add annotations like
[Display("User Id")]
Required(ErrorMessage = "Please input the Id")
public int Id { get; set; }
But I need use multiple language , So I create a new DataAnnotations Attribute(https://stackoverflow.com/a/2432520/1900498):
public class LocalizedDisplayAttribute : DisplayNameAttribute
{
public LocalizedDisplayAttribute(string resourceId)
: base(GetMessageFromResource(resourceId))
{ }
private static string GetMessageFromResource(string resourceId)
{
// TODO: Return the string from the resource file
}
}
It works fine , but it will cache the result, then when session changed(I'm use session save the user website page language mode. like 1 mean English, 0 mean other language), it still not change, this is a problem for me.
second problem is: I don't know how to rewrite RequiredAttribute for let user know , some field can't empty.
but I also find there is another problem , looks like I need to rewrite the message about numeric field......(xx field must be numeric)
So Is there any way can rewrite the validation rule, let me decide the error message for Required, Range, Numeric...... and it will cache it but when session changed, it will read again?
For example:
// if session changed rewrite rule message for current language
if (session["language"].ToString() != LastLanguage)
{
if (session["language"].ToString() == "1")
//English
{
RequiredMessage = "the field {0} must be required";
NumericMessage = "the field {0} must be a number";
LastLanguage = 1;
} else{
// other language
RequiredMessage = "xx xx {0} xxxxxxxxx";
NumericMessage = "xx xx {0} xxxxxxxxxx";
LastLanguage = 0;
}
}
Of course, not only the validation message, I need globalization the field display name too.
DataAnnotation already provides globalization support:
[Display(ResourceType = typeof(Resource), Name = "Test")]
[Required(ErrorMessageResourceType = typeof(Resource), ErrorMessageResourceName = "TestRequired")]
public string Test { get; set; }
To change the current culture in the global.asax
private void Application_AcquireRequestState(object sender, EventArgs e)
{
if (Context != null && Context.Session != null)
{
string language = Context.Session["language"] as string;
if (language != null)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo(language);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language);
}
}
}

Categories

Resources