Formatting C# Chart Axis Using CultureInfo - c#

Currently i set Y axis of my chart using N2 format like this
chart.ChartAreas[0].AxisY.LabelStyle.Format = "{0:N2}";
What i want to achieve is that N2 is using Indonesian format, i know how to do it in object conversion just like below
sum.ToString("N2", CultureInfo.GetCultureInfo("id-ID"));
How to apply CultureInfo in formatting chart axis?

You can use the FormatNumber event of the chart.
private readonly CultureInfo indonesiaCulture = CultureInfo.GetCultureInfo("id-ID");
void chart1_FormatNumber(object sender, FormatNumberEventArgs e)
{
if (e.ElementType == ChartElementType.AxisLabels)
{
e.LocalizedValue = e.Value.ToString("N2", indonesiaCulture);
}
}
Or you can change the Thread.CurrentUICulture for the UI thread and set LabelStyle.Format property. I've not tested it, I believe that should also work.

In addition to Sriram Sakthivel's answer.
You can use Format property this way:
chart.ChartAreas[0].AxisY.LabelStyle.Format = "IndonesianNumericFormat";
void chart_FormatNumber(object sender, FormatNumberEventArgs e)
{
switch (e.Format)
{
case "IndonesianNumericFormat":
e.LocalizedValue = e.Value.ToString("N2", new CultureInfo("id-ID"));
break;
}
}
So, you can set different formats to different columns and incapsulate logic of string conversion to a class \ factory etc.

Related

WPF DataGrid using wrong NumberDecimalSeparator

currently I am facing the following problem.
In my application (which is a plugin for AutoCAD/BricksCAD), i am using a DataGrid with a custom Column, that ensures the input to be in a float-format.
The code for the column looks something like that:
public class DataGridFloatColumn : DataGridTextColumn
{
protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
{
TextBox edit = editingElement as TextBox;
edit.PreviewTextInput += OnPreviewTextInput;
return base.PrepareCellForEdit(editingElement, editingEventArgs);
}
void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
string txt = ((TextBox)sender).Text + e.Text;
float _;
e.Handled = !float.TryParse(txt, out _);
}
}
This part works as expected. I am only allowed to input float numbers, separated by a comma. The problem however is, that the DataGrid expects a dot as decimal separator.
Due to this, initial values are represented with a dot, and If I type something with a comma, it simply gets removed when hitting enter... for example 123,4 --> 1234
What I have already tried:
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("de-DE");
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("de-DE");
But when printing Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator, i am getting a comma...
Any suggestions?
Thank you ind advance!
I dont know if it covers your issue, but if I want culture-specific number/datetime formatting in XAML, I put this "hack" into the constructor of my "App.xaml.cs"
public App()
{
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage("de-DE")));
}
Thread.CurrentThread.CurrentCulture = myCulture somehow does not do the trick.

Change Language/Resource programmatically w/ WPF

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");

How to apply a textbox formatting method to all textbox controls

OK, so I am trying to apply the accounting number format for all textboxes on my Form.
Now, I did some research here and found this post that will help me to set the format.
And then I found another post to apply the format for all textbox controls on the form without adding the format code individually to all controls.
Well, the thing is that the code on the format uses the control name, which will bind it to a single textbox control. I tried the control name (TextoBox) instead, and it also failed.
There is another issue to consider, that even if I manage to get past the above problem, the code from format is an event, named after the control name, so I do not think it will work if I apply it to a class or method and call for it.
While I already do have the solution to what I want, I would like to know if there is a faster way to apply it, which will not add so much lines to my code. Trying to learn how to keep things easier to read, doing less with more. Any advise?
Thanks for reading.
It sounds like you have all the pieces, just need help putting it together. For the ControlName, you can cast the sender object to the control and access its Name property.
void SetProperty(Control ctr)
{
foreach (Control control in ctr.Controls)
{
if (control is TextBox)
{
control.Leave += control_Leave;
}
else
{
if (control.HasChildren)
{
SetProperty(control);
}
}
}
}
void control_Leave(object sender, EventArgs e)
{
var textBox = sender as TextBox;
Double value;
if (Double.TryParse(textBox.Text, out value))
textBox.Text = String.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:C2}", value);
else
textBox.Text = String.Empty;
}
Usage:
SetProperty(this);
Also, from my comment on the OP: If accounting is truly important, I would suggest using the Decimal type instead of Double. Double will be faster, but Decimal is more precise. Figure out which trade off makes sense and make a decision based on that.
Edit per comments:
myTextBox.Leave -= control_Leave
If you know the name of the control, the above will work. You will need to do this after you use SetProperty(this). If you want to handle this inside the SetProperty() method, do a check on control.Name == "myTextBox".
You can subscribe multiple controls event(that use the same args) to the same event handler :
public YourFormConstructor()
{
foreach(var textbox in form.Controls.OfType<TextBox>())
textbox.Leave += FormatCurrencyText;
}
private void FormatCurrencyText(object sender, EventArgs e)
{
var textbox = sender as TextBox;
Double value;
if (Double.TryParse(textbox.Text, out value))
textbox.Text = String.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:C2}", value);
else
textbox.Text = String.Empty;
}

How to extend TextBox's properties to create a RichTextBox?

My Question is to how to extend a TextBox such that it may start behaving like RichTextBox?
There can be various properties that RichTextBox may add: appearance mainly.
Should I use this kind of method where I extend the TextBox class and create a basic TextBox which would contain several other textboxes which would behave like a big container node containing small specialized nodes?
For starters, to have texts with alternate color after '+', I ve used this way:
class CustomTextBox : TextBox
{
List<TextBox> _textboxes = new List<TextBox>();
string _Text="";
List<Color> colorlist = new List<Color>();
public override string Text
{
get{return this._Text;}
set{this._Text = value;}
}
public CustomTextBox()
{
foreach(Color color in (Color[]) Enum.GetValues(typeOf(Color)))
{
colorlist.add(color);
}
this.KeyUp+= new KeyUpEventHandler(TextChangedCheck);
}
int i=0;
private void TextChangedCheck(object sender, KeyUpEventArgs e)
{
if(e.KeyData == Keys.Add)
{
TextBox Temp = new TextBox();
Temp.Text = this.Text;
this.Text = "";
Temp.ForeColor = colorlist[i];
i++;
this._textboxes.Add(Temp);
this.Controls.Add(_textboxes[i]);
e.Handled = true;
}
}
}
EDIT:
The MAIN purpose of this question is to extend a TextBox using its own properties to have a RTB like behavior and not using Graphics or related.
I'd have to guess what you really want to achieve here.
But if you want a Control with formatted text (FT) and really really really don't want a RichTextBox, I think you shouldn't create a new, embedded TextBox for every piece of FT.
Instead you should write the FT yourself, maybe on a panel with DrawString and use only one Textbox for text entry. Interesting project, really, once one accepts the challenge. Of course you must think your format through and also consider all sorts of interface questions..
Last week I have avoided a RTF for a tiny help system by using a ListView; it formats by line only, using the first character to indicate the format from a list of a dozen or so.. Works fine, but only one format per line.

How to format currency by CultureInfo in DevExpress XtraCharts?

I am creating charts programmatically in a manner similiar to this example on the DevExpress website. I see where you can identify series data to be formatted as currency, but the reporting tool is globally based and needs to be able to format the various chart labels using a passed in currency.
Here is an example of code used to generate a typical SeriesView:
private void FormatBarSeries (SideBySideBarSeriesView bar)
{
bar.AxisY.NumericOptions.Format = NumericFormat.Currency;
bar.AxisY.NumericOptions.Precision = 0;
bar.AxisY.Title.Text = "Sample Bar";
bar.AxisY.Title.Font = new Font(GetChartFontFamily(), 10.0f, FontStyle.Regular);
bar.AxisY.Title.Visible = true;
bar.AxisY.Tickmarks.Visible = false;
bar.AxisY.Tickmarks.MinorVisible = false;
bar.AxisX.Tickmarks.MinorVisible = false;
}
I cannot seem to find any manner of defining the culture for the specific chart. Each report may contain multiple charts, but all the charts on a report would be the same currency format.
Can this perhaps be set at the report level and have all charts inherit it? Or how can I set this on a chart by chart basis?
Found the answer, as demonstrated here:
You have to hook into a CustomDrawAxisLabel event:
Chart.CustomDrawAxisLabel += Chart_CustomDrawAxisLabel;
where you can override the code with a function like this:
void Chart_CustomDrawAxisLabel (object sender, CustomDrawAxisLabelEventArgs e)
{
AxisBase axis = e.Item.Axis;
if(axis.NumericOptions.Format == NumericFormat.Currency)
{
decimal value = 0.00M;
e.Item.Text = decimal.TryParse(e.Item.AxisValue.ToString(),
out value)
? value.ToString("C0", _culture)
: e.Item.AxisValue.ToString();
}
}
using a culture variable defined elsewhere in the class.

Categories

Resources