Silverlight (RIA Services) spontaneous culture changing - silverlight

My RIA enabled Silverlight Application is setting the thread culture in the App constructor (this is absolutley okay since it is an intranet application and will never ever be used by someone who is not german):
public App() {
InitializeComponent();
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
}
It does what it should, the DataForms are displaying datetime values in german notation. BUT: it is spontaneously changing to en-US notation when navigating between items in the data source that is bound to the DataForm. Why?

It seems that the thread culture is not inherited by every control. Just for fun I displayed the Language of the control, and it was alwas set to en-US. To solve this, I hard coded the language de-DE in the style for the DataForm.
The same problem was described by Hannes (in german). Surprisingly in this case it was exactly the other way round: the DataForm was german, but the grid was english.

As Marc Wittke said, the thread culture is not inherited by every control (why on earth???)
Any way, you do not need to hardcode the values, this put this line in your Control constructor:
Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.Name);
And you control will use the CurrentCulture.
Cheers,
André

Related

Hosted Winform control does not respond to events from WPF

This is my first question in StackOverflow. Due to lack of reputations, I couldn't post any links or images.
I've been working on the following issue for more than 2 days. Any help would greatly be appreciated.
Before I get into my question, here is what I have and what I'm expecting:
I have a Windows Form which hosts WPF in an ElementHost control.
And then, I have a Winforms UserControl similar to DateTimePicker. This
is hosted inside a WindowsFormsHost control.
The above scenario is un-avoidable for the following reasons:
The authorization dialog to all our applications is developed in
Winforms, and takes a Winforms instance as its parameter. There is no
WPF version introduced yet. Therefore, I had to use an ElementHost to
host my View inside the Windows Form.
The Winforms control hosted inside my WPF is also un-avoidable. We
have our own DateTime Winforms UserControl that behaves similar to
the DateTimePicker Winforms control, but has lot more complexities
involved. So, replacing this control with a WPF version is out of
question.
Expected Functionality:
I have a
WPF control (say, a textbox)
A DateTime Winforms UserControl that I was mentioning above.
And a Cancel button that basically resets the above controls.
When I hit the Cancel button, I'm publishing an event from the ViewModel, say RunViewModel to the WPF UserControl code behind file, say RunView.xaml.cs.
eventAggregator.GetEvent<ResetDateTimeEvent>().Publish(true);
In the code behind file, I've subscribed to the event as follows
eventAggregator.GetEvent<ResetDateTimeEvent>().Subscribe(ResetDateTimeHandler);
The WPF control resets to its default value, but the DateTime UserControl does not reset.
So, for testing purposes, I removed the ElementHost control, and just had my WPF View with a WindowsFormsHost control that hosts the DateTime Winforms UserControl, and a WPF "Cancel" button.
When I click on the button, the value on the DateTime control resets to its default value.
Then, I thought this might be an issue with my DateTime Winforms UserControl.
So, I replaced my DateTime Winforms UserControl with a Winforms Textbox control in my actual application. So now the nesting is as follows:
WinForms-ElementHost-WPF-WindowsFormsHost-Winforms Textbox
Here is the xaml code.
<WindowsFormsHost x:Name="ReportFromDtTmHost" Margin="8,0" Grid.Column="0"
LostFocus="ReportFromDtTmHost_LostFocus">
<WindowsFormsHost.Child>
<winforms:TextBox x:Name="ReportFromDateTime"/>
</WindowsFormsHost.Child>
</WindowsFormsHost>
On Initial load, I’m loading the Textbox with Initial Load Text text
private void Window_Loaded(object sender, EventArgs e)
{
ReportFromDateTime.Text = "Initial Load Text";
}
As I was mentioning above, when I hit the Cancel button, this is what happens:
Publish the event from ViewModel
eventAggregator.GetEvent().Publish(true);
Subscribe to the event in the code behind file (xaml.cs):
eventAggregator.GetEvent().Subscribe(ResetDateTimeHandler);
EventHandler for the published event.
private void ResetDateTimeHandler(bool cancelClicked)
{
ReportFromDateTime.Text = "Reset to Default";
}
As you can see in the above code, I’m resetting the Text on clicking the Cancel button.
During Debugging, I could see the Text property being changed to "Reset to Default", but the UI does not show these changes.
Here is the wierd part:
The Child property on the WindowsFormsHost control is different from the actual “ReportFromDateTime” Textbox control.
While debugging, I could see that the Child and Name property on the WindowsFormsHost control were different.
The Name property is empty,
ReportFromDtTmHost.Child.Name = ""
which rather should be ReportFromDateTime.
It almost seems like the Host and the Child controls are getting re-created.
As far as I see it, I think the extra level of nesting (WinForms-ElementHost-WPF-WindowsFormsHost-Winforms Textbox) might be causing issues during the interoperations between WPF and Winforms.
I’ve done a lot of research and searched lot of links for suggestions. I found none pointing out this issue. Some of them were close. Here are a couple of links:
The this suggests to reproduce the message loop under the “Surrogate Windows Forma Message Loop” section.
Here is one more link that explains the issue with nesting under the Nesting section.
I apologize for being verbose. Just wanted you guys to get a clear picture of my problem. Please let me know if you have any questions regarding the post. Any suggestions would be greatly appreciated.
EDIT:
We were able to resolve the issue, but still, it is a work-around. Here is what we did:
There were two ways to resolve this issue, but both were related to using static.
Static Winforms control:
We used the following static Winforms control
public static class ControlHolder
{
public static TextBox ReportFromDateTimeInstance;
}
In the OnChanged event of the "actual" control, we dump the actual control, ReportFromDateTime to the static control, ReportFromDateTimeInstance.
private void ReportFromDateTime_TextChanged(object sender, EventArgs e)
{
ControlHolder.ReportFromDateTimeInstance = (TextBox)sender;
}
And from then on, wherever we update the actual control (as in ResetDateTimeHandler method), we update the static control
private void ResetDateTimeHandler(bool cancelClicked)
{
ControlHolder.ReportFromDateTimeInstance = "Text changed";
}
This shows the updated value on the Front-End
Static EventAggregator
This work-around was provided by one of our colleague.
In this case, we are using our actual control, ReportFromDateTime, rather than the static control, ControlHolder.ReportFromDateTimeInstance
We used a static event aggregator for publishing/subscribing the ResetDateTimeEvent instead of using the Event Aggregator instance provided by Unity Container. So, instead of
eventAggregator.GetEvent<ResetDateTimeEvent>.Publish(true);
we used:
ResetDateTimeEvent.Instance.Publish(true);
And in the subscription:
ResetDateTimeEvent.Instance.Subscribe(ResetDateTimeHandler);
I know that we need not use a static event aggregator in this scenario since we are using the instance provided by Unity Container (which makes sure that a single instance is shared by all the ViewModels), but this also has resolved the issue.
So, I'm still confused on why the above two scenarios are solving the problem. Is it the static-ness that is solving the issue ?
As I was already saying, I feel that the controls are getting re-created, and by the time we have the controls in hand, they have been already re-created.
Any suggestions would greatly be appreciated.
I've done the same thing before in an app that had a WPF control inside of a WinForms control. The WPF used Prism/Unity (later switched to MEF) to start everything up. However, this created a whole new EventAggregator by default in the bootstrapper, so I had override the default IEventAggregator in the container with a static one b/c the WinForm side had already been created and was using its own IEventAggregator instance. The symptom was similar in that published events were not received.
In a mixed system such as yours, singletons are great for ensuring that everything's feeding off of the same reference, especially when your startup is in stages (WinForms then WPF).
Simple answer: yes, use singletons for shared references between WinForms code and WPF code. Those singletons can be fed into the container in the WPF bootstrapper so that injection still occurs in the WPF side, too.

WinForms PropertyGrid behaving unexpectedly in WPF app

I'm using the WinForms PropertyGrid to edit object properties in a WPF app. However, the PropertyGrid isn't working as expected with certain property types. Specifically, objects exposing properties of type Color or Brush are displayed as text, #FF000000, for example, and the drop-down color selector list doesn't appear when a cell of that type is clicked in the PropertyGrid. It is my understanding that built-in editors exists for these types and I shouldn't have to do anything extra to get this to work (please correct me if I'm wrong).
For sake of brevity, I won't include a gazillion lines of code, but suffice to say that everything is pretty boilerplate. My implementation is culled straight from MSDN, SO or the myriad of WPF PropertyGrid examples floating around on the web. The PropertyGrid is wrapped in a WindowsFormsHost which goes into a Window that pops up whenever a user wants to edit an object. Something akin to this:
`<Window>
<Grid>
<WindowsFormsHost>
<PropertyGrid>
...
</PropertyGrid>
</WindowsFormsHost>
</Grid>
</Window>
// BTW everything's implemented in code.
The actual objects are of course not passed to the PropertyGrid directly, but wrapped in custom PropertyEditorObjects which expose only those properties of interest in a predefined way, and at times these PropertyEditorObjects may implement an ICustomTypeDescriptor, especially when the objects being edited have child objects whose properties also need to be exposed to the PropertyGrid as nested properties. Generally:
public class PropertyEditorObject
{
...
property bool SomeProperty { get; set; }
property Size AnotherProperty { get; set; }
property Brush YetAnotherProperty { get; set; }
[TypeConverter(typeof(ExpandableObjectConverter))]
property ContentProperties MoreProperties { get; }
};
public class ContentProperties : ICustomTypeDescriptor
{
// Implements all the usual ICustomTypeDescriptor stuff.
}
// The PropertyGrid.SelectedObject is set to an instance of the PropertyEditorObject.
Everything works with the exception of what I mentioned at the start of this post: that certain property types (Colors, Fonts, etc.) are displayed as text only and the PropertyGrid doesn't use the proper Editor for that type.
The reason I'm asking fro help with this is because I'd like to use the built-in WinForms editors, such as the ColorDialog, FontDialog, etc. to edit these types without having to reinvent the wheel as my app is only in the demo stages. Any direction on this matter would be greatly appreciated. Thanx.
This is to be expected. The WinForms property grid knows nothing of WPF types like Color, Brush, or FontFamily, so it has no custom editors for them. Have you tried one of the third-party WPF property grids? I believe the Extended WPF Toolkit has one.
My temporary solution: Install Extended WPF Toolkit Plus, use the PropertyGrid Plus (which has a SelectedObject*s* property) as the editor, wait for the 'fix' in v2.3 that will allegedly support more 'types' (Shapes, spinning squigglies with flames shooting out the sides, the letter 'a', etc.) and, in the meantime if a user attempts to edit an unsupported 'type', throw an exception stating sorry, but you should really send us some money first. That's all for now. More sarcasm available as soon as I invent it. Thanx to the commenters for their suggestions. Toodles.
Update on solutions:
1) Use the Winforms PropertyGrid, as stated in the original post, add EditorAttributes to properties that need them, e.g. Colors, Fonts, etc., and open the Winforms ColorDialog, FontDialog, etc., to edit them. Requires some type conversion but only a few lines of code. Not the best solution, but WORKS.
2) Use the Extended WPF Toolkit PropertyGrid. Works, sorta, but with limitations. Doesn't support all types nor multiple-object selection, i.e. no SelectedObjects property. The first issue is to be fixed in v2.3 of the Toolkit. The second is sort of a showstopper without writing wrappers to facilitate the functionality.
3) Use the Extended WPF Toolkit Plus, PropertyGrid Plus. Allows for multiple-selection, but still suffers from limited type selection. Also, costs big dinero.
4) Use the WWF PropertyInspector as a WPF PropertyGrid. Looked good on paper, but wound up functioning no better than the WinForms PropertyGrid. Requires editors/converters.

C# Winforms Custom control, binding on propertychange is not working and causing tabbing issues

I've just upgraded an old .NET 1.1 Winforms app that uses CSLA to .NET 4.0 and a later version of CSLA which supports the use of the INotifyPropertyChanged interface.
A large part of the reason for doing this is the databinding improves - e.g. being able to update on change when binding instead of when validating (tabbing off).
I have custom user control, NumberBox. Essentially it's just a textbox with a few properties such number type, decimal places etc.. I have exposed a public property of type object called BindableValue. It was this property that I was binding my CSLA classes (standard .NET classes inheriting validation rules, property changed and various stuff) integer property to, in this particular case it the class property is integer.
My problem having upgraded are the following:
If I enter a value, e.g. 1234, into my number box control it doesn't push the value back into the class' property it is bound to until I tab off, even though I have configured an object binding source to the custom BindableValue property with the update mode set to Property change.
Having entered value as in (1) if I go back and delete the value I am then prevented from tabbing off or clicking off the number box. I have set VS2010 to throw when .NET exception is thrown but it's not breaking.
It's been a while since I did WinForms stuff so I'm at a bit of a loss where to start. Any tips as well as a solution would be much appreciated.
EDIT:
I've tried a number of different things and am getting nowhere fast, it's getting really frustrating now:
I followed the info on MSDN, i.e. I added a ComplexBindingProperties attrib, slightly different in the textbox's private keyUp event handler I raise the event as indicated by the linked article OnBindableValueChanged(). However in all cases my event BindableValueChanged is always null.
I read similar articles to (1) but instead of declaring the event using EventHandler they used PropertyChangedEventHandler, tried this same result.
I added the DefaultBindingProperty attrib.
[You can read about this experience on my companies blog too - OCC Blog - Binding woes ]
I finally figured it out so thought I'd share it here to save someone else the tedium of trawling through Google reading lots of responses that say they work but in .NET 4.0 no longer seem to apply.
Okay, a lot of stuff I was reading on Google kept telling me my usercontrol had to have a Changed event using either EventHandler or PropertyChangedEventHandler delegates - different pages indicated different delegate. I tried both - fail!
What I had to do in .NET 4.0 is actually much nicer. Simply put just like my class that I was binding my usercontrol to does I had to implement the INotifyPropertyChanged interface. Then in my usercontrol when I wanted to pushback into my source object I just raised the PropertyChanged event (e.g. PropertyChanged("BindableValue"); ) the interface defined and hey presto all was well with the world again.
This above is a lot more elegant but unfortunately articles, forums and posts that are indexed by Google have not caught up with this yet for .NET 4.0 so all the existing stuff will lead you down dead ends and much frustration. I hope this saves someone else a lot of time.

WINRT TextBox Number Formatting not respecting Current Culture

I am binding a float property to my TextBox control. Thats working correct if I am using "en" as my language Preference.
Entering a number "1.123" is correctly parsed.
If I Switch mur culture to "de" nothing changes in the TextBox (and TextBlocks). Still everything is formatted with a ".".
Entering a number via the "Numeric" Keyboard of WinRT is using the "," as a seperator. But the Training Digits will not be part of the number after Focus lost (and the bound property is updated.
So "1,234" should be parsed internaly as "1.234". But ist converted to "1".
The app.xaml.cs contains some more initialisation for ensuring the culture is set to the right language. The allowed languages are ("en" and "de" (*,proj file.
The CultureInfo.CurrentCulture is correctly set to "de" if you break into debugger.
public App()
{
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = CultureInfo.CurrentCulture.Name;
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CurrentCulture;
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CurrentCulture;
Setting PrimaryLanguageOverride, DefaultThreadCurrentCulture, and DefaultThreadCurrentUICulture in the Application constructor has no effect, since they only apply to new threads. However, your main UI thread has already been created an had its culture set by the time the constructor is entered.
To force a change to the existing UI thread, you'd have to set Thread.CurrentCulture as documented in CultureInfo.CurrentCulture; however, WinRT does not support the Thread class.
This leads to the question of why any manual cultural changes are required at all. The app should automatically pick up the user's Windows culture at startup or upon resuming from hibernation.
To get the InvariantCulture settings we can use,
"ApplicationLanguages.PrimaryLanguageOverride = CultureInfo.InvariantCulture.TwoLetterISOLanguageName;"
This worked for me.

Silverlight Date Formats

I'm getting some very strange date formatting issues in my Silverlight application. My local culture is set to UK, yet I am consistently seeing US dates popping up all over the place. I can easily hardcode these to UK format in specific loactions using:
<UserControl ... Language="en-GB"...>
But as I'm sure you'd all agree this is a terrible thing to do.
I have tried setting the Lanaguage to en-GB in the main application and this has partial success. I have also tried Justin Angels suggestion (posted here: How to change date format in Silverlight DatePicker control?), again only partial success.
An example of the issue can be seen here:
http://lh3.ggpht.com/%5FL9TmtwXFtew/Sw5aVZJfG1I/AAAAAAAAGkI/6jYnsB91HjI/image%5Fthumb%5B1%5D.png http://lh3.ggpht.com/%5FL9TmtwXFtew/Sw5aVZJfG1I/AAAAAAAAGkI/6jYnsB91HjI/image%5Fthumb%5B1%5D.png
The datagrid on the parent page shows UK formatting, whilst the information in the ChildWindow shows US formatting ...grrrr
Anyone have a definitive solution for solving this across a whole application?
Thanks,
Mark
You can data bind Language property of the root visual element. Take a look at my question here:
How to switch UI Culture of data binding on the fly in Silverlight
Can you not use the SelectedDateFormat property of the datepicker? If you want to do this once could you not create your own usercontrol that derives from the original with this value preset, then use your derived control throughout your app?
Kindness,
Dan
Shot in the dark, but does changing the browser's Language Preference make a differnence? I.e. in IE Tools-->Internet Options-->Languages.
HTH
Mark
You can set the date format for your entire application in the application start up event as follows.This will override any regional settings on the users machine
Thread.CurrentThread.CurrentCulture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern = dd/MM/yyyy";

Resources