Silverlight ignoring CurrencyGroupSeparator - silverlight

Thread.CurrentThread.CurrentCulture = New CultureInfo("sv-SE")
Thread.CurrentThread.CurrentUICulture = New CultureInfo("sv-SE")
Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyGroupSeparator = " "
Thread.CurrentThread.CurrentUICulture.NumberFormat.CurrencyGroupSeparator = " "
Im trying to do:
<TextBlock Text={Binding decimalValue, StringFormat=c2}/>
It sets the culture properly and adds the "kr" which is the swedish currency symbol. However, doesnt honor the group separator setting. Even if I set it to "-" or whatever it doesnt work.
Big questionmark? Bug?

I am not sure if you were able to work around this problem, but since nobody answered, I will.
For starters, I am not sure if your backing code runs in the same thread as presentation layer; probably not, that is I believe Silverlight creates its own visual thread. In other words setting thread-wide CultureInfo will not resolve your problem.
There are (at least) two ways to resolve this issue:
1. Play with StringFormat attribute to set custom format.
2. Create dynamic property in the backing code which will format the value for you. Please find this imperfect example:
public decimal Quote { get; set; }
// Formats value of Quote property
public string FormattedQuote
{
get
{
CultureInfo swedishCulture = new CultureInfo("sv-SE");
swedishCulture.NumberFormat.CurrencyGroupSeparator = " ";
return Quote.ToString("c2", swedishCulture);
}
}
And in your XAML code, you do not need specify format, so you would only do this:
<TextBlock Name="textBlock1" Text="{Binding FormattedQuote}" DataContext="{Binding ElementName=textBlock1}" />

Related

How do I resolve Non String values, when using a WebService to access SqlServer

I'm currently trying to build a UWP app that points to a SqlServer, and thru much research, determined that my best plan of attack was to create a WebService and make EF Calls to "CRUD" the dbase.
I found a good tutorial that helped a lot, however, I'm still new at this so seeing what some else did, and adapting is a learning experience. So it has caused a few questions to come up, that I have yet to solve.
These are my question;
HostName below is an INT in the Database and POGO Class.. So I'm getting the "cannot implicitly convert type 'int' to 'string'" error. How do I resolve this? Do I use StringFormatConverter that is part of the Template I'm using?
The last value, EMV is a boolean value. It is currently pointing to a Toggleswitch and is pointing to the IsOn property of the Control. Will that resolve correctly?
Lastly, I would like to keep as much of my code adherent to the MVVM format. So If I move the below code below from Code Beyond to the ViewModel would that perform better?
Here is the Code Behind inside the Click Event...
private async void Save_Click(object sender, RoutedEventArgs e)
{
var tblDevice = new Device { HostName = hostNameTB.Text, Server =serverIPTB.Text, RouterName = routerNameTB.Text, IP = iPTB.Text, Gateway =gatewayTB.Text, Hardware = hardwareTB.Text, EMV = eMVTB.IsOn};
var deviceJson = JsonConvert.SerializeObject(tblDevice);
var client = new HttpClient();
var HttpContent = new StringContent(deviceJson);
HttpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("Application/json");
await client.PostAsync("http://localhost:2463/api/Devices", HttpContent);
Frame.GoBack();
}
Here is the XAML
<TextBox Name="hostNameTB" />
<TextBox Name="serverIPTB" />
<TextBox Name="routerNameTB" />
<TextBox Name="iPTB" />
<TextBox Name="gatewayTB" />
<TextBox Name="hardwareTB" />
<ToogleSwitch Header="EMV" IsOn="False" Name="eMVTB" OffContent="UnConfigured" OnContent="Configured" />
1 Int32.Parse(hostNameTB.Text) or via the Converter your choice.
2 Yes it will come thru as a 1 or a 0, true/false etc. In the DB I assume this a
BIT type?
3) it will perform the same only difference is testability

ValidateWithoutUpdate doesn't ever execute configured ValidationRules?

I'm trying to understand why calls to BindingExpression.ValidateWithoutUpdate() doesn't actually do what it advertises.
I've got some cranky validation (I've removed the boring details from my sample code; suffice it to say it has to do with WF4 ModelItem limitations) that I have to add to a binding via an attached property (e.g., from code and not in xaml).
// d is DependencyObject and prop is DependencyProperty
var binding = BindingOperations.GetBinding(d, prop);
binding.ValidationRules.Add(new MyDerpyValidatonRule());
Nothing crazy here. But the problem is that validation isn't run the first time the control is shown, so validation errors are not exhibited in the UI.
<TextBox
Grid.Column="1"
x:Name="derp"
Text="{Binding Derp, NotifyOnValidationError=True,
ValidatesOnDataErrors=True}"
t:MyDerpyValidator.TargetProperty="{x:Static TextBox.TextProperty}" />
Binding looks good, works after the value is changed, but when first shown, I get a frownyface instead of the expected red Border:
Initially, I tried calling ValidateWithoutUpdate after I added the ValidationRule to the Binding. This didn't seem to work. Later, I used the Dispatcher to try and put this call off until the application was all warm and cozy (maybe it didn't validate because the tea hadn't finished brewing yet, hell I dunno)
var exp = BindingOperations.GetBindingExpression(d, prop);
Dispatcher.CurrentDispatcher.BeginInvoke(
(Action<BindingExpression>)(x =>
{
x.ValidateWithoutUpdate();
}),
DispatcherPriority.ApplicationIdle,
exp);
I'm pretty sure this worked once. Once. Never worked again. Might have been an incorrect observation on my part.
Later, I tried all kinds of things to get ValidateWithoutUpdate to actually do something. I even tried calling it from within an event handler that would happen way down the road
public DerpyControl()
{
InitializeComponent();
derp.MouseEnter += DERPDAMNYOU;
}
void DERPDAMNYOU(object sender, MouseEventArgs e)
{
derp.GetBindingExpression(TextBox.TextProperty).ValidateWithoutUpdate();
}
It never friggen works.
What do I need to do to get BindingExpression.ValidateWithoutUpdate() to friggen validate?!?!
Wow, that's some weird behaviour. Looking at some of the validation code with ILSpy it has some checks in the background that determine if validation is required or not, and I was too scared to follow it all the way through, so, I too, just tried some random stuff.
This is the first thing I tried that worked:
In your attached property changed handler, after
binding.ValidationRules.Add(new MyDerpyValidatonRule());
add
BindingOperations.ClearBinding(d, prop);
BindingOperations.SetBinding(d, prop, binding);
This must somehow set the internal 'validation requred' flag which forces it to validate.
The solution for my project was:
var binding = BindingOperations.GetBindingExpression(textbox, TextBox.TextProperty);
binding.UpdateSource();
binding.ValidateWithoutUpdate();

How to display application title in XAML text field

I have a Windows Phone page code that is shared by multiple applications.
At the top of the page, I show the title of the application, like so:
Is it possible to make the text be bound to the application title as defined in the application's assembly?
I realise that I could do this by code by reading the title in the assembly and then doing something like:
this.ApplicationTitle.Text = title;
I was hoping that the title as defined in the assembly could be accessed with some magic like:
Text={assembly title}" directly from within the xaml.
Thanks
Create a property called ApplicationTitle that returns that name of the application like the following, and then bind to it in XAML:
public string ApplicationTitle
{
get { return System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; }
}
(You can use a relative binding source if you can't or don't want to use the data context.)
edit:
I just realized that my method involved security considerations since GetName is a method that is [Security Critical]. And I got a MethodAccessException stating: Attempt to access the method failed: System.Reflection.Assembly.GetName()
So here's another way to get the assembly name and return it in a property by using the AssemblyTitle attribute.
public string ApplicationTitle
{
get
{
System.Reflection.AssemblyTitleAttribute ata =
System.Reflection.Assembly.GetExecutingAssembly().GetCustomAttributes(
typeof(System.Reflection.AssemblyTitleAttribute), false)[0] as System.Reflection.AssemblyTitleAttribute;
return ata.Title;
}
}
To bind in XAML, you can use this:
Text="{Binding ElementName=LayoutRoot, Path=Parent.ApplicationTitle}"

How to use Windows' Customized Region and Language settings in WPF

I am working in Namibia. Namibia is not an option on the Windows Region and Language settings, but share most cultural specifics with South Africa, so we select English South Africa and then customize the currency symbol to be "N$" (Namibian Dollars) and not "R" (South African Rand).
However, I can't convince WPF to use the customized currency. Using string.format("{0:c}", foo) in code works fine, but using {Binding Path=SomeCurrencyValue, StringFormat=c}` in XAML still uses the "R" symbol and not the custom "N$" symbol.
In App.xaml.cs I set the Application Culture with the following code:
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(System.Globalization.CultureInfo.CurrentCulture.LCID, true);
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement),
new FrameworkPropertyMetadata(
System.Windows.Markup.XmlLanguage.GetLanguage(
System.Globalization.CultureInfo.CurrentUICulture.IetfLanguageTag)));
As demonstration, here is some XAML code that shows the problem:
<StackPanel>
<TextBlock>
Formatted in XAML with: <LineBreak/>
Text="{Binding Path=SomeCurrencyValue, StringFormat=c}" <LineBreak/>
Result:
</TextBlock>
<TextBox Text="{Binding Path=SomeCurrencyValue, StringFormat=c, Mode=OneWay}"
Margin="5"/>
<TextBlock>
Formatted in code with: <LineBreak/>
return string.Format("{0:c}", SomeCurrencyValue); <LineBreak/>
Result:
</TextBlock>
<TextBox Text="{Binding Path=SomeCurrencyString, Mode=OneWay}"
Margin="5"/>
</StackPanel>
The DataContext for the above View contains the following:
public double SomeCurrencyValue
{
get { return 34.95; }
}
public string SomeCurrencyString
{
get
{
return string.Format("{0:c}", SomeCurrencyValue);
}
}
And the result looks like this:
I know there is a similiar question here, but I was hoping to get better answers with a more complete question. I am mostly working on financial applications for Namibian clients, so this is quite a serious issue for me - if there is no way to do this with .NET 4.0, I would consider filing a bug report, but I just wanted to check here first.
EDIT:
Just opened up the bounty on this question. I'm hoping for either a solution that isn't a rediculous workaround, or confirmation that this is a bug and should be filed as such.
One solution to this is to create this Namibian CultureInfo, so its fully recognized by all .NET layers. Here is a code that does it:
public static void RegisterNamibianCulture()
{
// reference the sysglobl.dll assembly for this
CultureAndRegionInfoBuilder namibianCulture = new CultureAndRegionInfoBuilder("en-NA", CultureAndRegionModifiers.None);
// inherit from an existing culture
namibianCulture.LoadDataFromCultureInfo(new CultureInfo("en-za"));
namibianCulture.CultureEnglishName = "Namibia";
namibianCulture.RegionEnglishName = "Namibia";
namibianCulture.CultureNativeName = "Namibia"; // you may want to change this
namibianCulture.RegionNativeName = "Namibia"; // you may want to change this
// see http://en.wikipedia.org/wiki/ISO_3166-1, use user-defined codes
namibianCulture.ThreeLetterISORegionName = "xna"; // I use x as 'extended' and 'na' as namibia
namibianCulture.TwoLetterISORegionName = "xn";
namibianCulture.ThreeLetterWindowsRegionName = namibianCulture.ThreeLetterISORegionName;
// see http://www.currency-iso.org/dl_iso_table_a1.xml
namibianCulture.ISOCurrencySymbol = "nad";
namibianCulture.CurrencyEnglishName = "Namibia Dollar";
namibianCulture.CurrencyNativeName = "Namibia Dollar"; // you may want to change this
// this is were you build something specific, like this symbol you need
namibianCulture.NumberFormat.CurrencySymbol = "N$";
// you'll need admin rights for this
namibianCulture.Register();
}
public static void UnregisterNamibianCulture()
{
CultureAndRegionInfoBuilder.Unregister("en-NA");
}
Once you have called the Register function once on a given machine (you will need to install this culture on end user machines), you can now use your initial WPF startup code, just change it like this:
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-NA");
And everything should work as expected. You can also use standard language tags and all that jazz, since en-NA is now recognized.
I had the same problem and I started from Simon's answer (thank you, Simon) making some modifications in order to get the user configuration (Region and Language in Control Panel) every time the application is launched, not the culture default.
My code look like this one
public MainWindow()
{
CreateAndRegisterLocalizedCulture();
this.Language = XmlLanguage.GetLanguage(customCultureName);
InitializeComponent();
DataContext = new ViewModel();
}
private void CreateAndRegisterLocalizedCulture()
{
CultureAndRegionInfoBuilder customCulture = new CultureAndRegionInfoBuilder(customCultureName, CultureAndRegionModifiers.None);
// Inherits from the current culture and region, may be configured by the user
customCulture.LoadDataFromCultureInfo(CultureInfo.CurrentCulture);
customCulture.LoadDataFromRegionInfo(RegionInfo.CurrentRegion);
// Not needed for the culture sake but...
customCulture.CultureEnglishName = CultureInfo.CurrentCulture.EnglishName + "-Customized";
customCulture.CultureNativeName = CultureInfo.CurrentCulture.NativeName + "-Customized";
// If the custom culture is already registered an unregistration is needed
// otherwise the following Register() call will generate an exception
if (CultureInfo.GetCultures(CultureTypes.UserCustomCulture).Where(ci => (ci.Name == customCulture)).Count() != 0)
{
// Admin rights are needed here
CultureAndRegionInfoBuilder.Unregister(customCulture);
}
// Admin rights are needed here
customCulture.Register();
}
It works fine to me but there are two problems in this approach:
In windows 7+ you need to start the application with Administrator rights as it will create a new culture file in C:\Windows\Globalization with the name you give to your custom culture
The Unregister method does not delete the above create file but it renames it as xyz.tmp0 and, with a logic I didn't get, time to time it creates more tmp file copies (xyz.tmp1, xyz.tmp2, ...). At least it is how it works in my pc.
Something that is not really a problem but a bit weird is that, once I change my regional settings in the control panel, I have to start my application twice before I see the modification. I can survive :)

silverlight application wide date

Is there a way to define a application wide format for the dates in Silvelight. So far I've tried to add this code in App_Startup:
CultureInfo culture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
culture.DateTimeFormat.ShortDatePattern = "dd-MM-yyyy";
culture.DateTimeFormat.FullDateTimePattern = "dd-MM-yyyy";
culture.DateTimeFormat.ShortTimePattern = "dd-MM-yyyy";
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
But all my date binding don't take this into consideration.
Regards,
Create a string resource in your App.xaml
<System.String x:Key="MyDateFormat">dd-MM-yyyy</System.String>
And use it as a static resource in your bindings' string format
<TextBlock Text={Binding MyDateProperty, StringFormat={StaticResource MyDateFormat}} />
I haven't tested this, but that would be my first try.
Try accepted answer from here - DateTime Not showing with currentculture format in Datagrid,ListView.
This works for WPF, you can try it for Silverlight to make it respect your culture.
There is a partial solution for this here: http://timheuer.com/blog/archive/2010/08/11/stringformat-and-currentculture-in-silverlight.aspx
This may not work at the application level though - you may need to apply the solution to various other classes e.g. your child windows.

Resources