Weird TextBox issues with .NET 4.5 - no '.' allowed - c#

I've got a really weird problem related to .NET 4.5.
Today a User told me that he isn't able to enter floating numbers into a Textbox (like "2.75").
The textbox just doesn't accept ".", which is the correct 'seperator' for floating numbers in my Culture ("de-CH").
This issue occurred after I compiled the software with .NET 4.5 (formerly it was 4.0).
I can reproduce this error. All other textboxes in the application are working fine.
The textbox is a regular WPF Control. No fancy user defined control or anything like that.
Again: the textbox just doesn't accept '.' as a character. It seems that it completely ignores it. Every other character (even special ones like "#") are fine.
Recompiling the application on .NET 4.0 solves the problem.
The xaml for the textbox is:
<TextBox x:Name="_Hours" Grid.Row="9" Grid.Column="1" VerticalAlignment="Center"
TextAlignment="Center" FontWeight="Bold" FontSize="16" Text="{Binding ProcessHours,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextChanged="Hours_TextChanged" />
Definition of ProcessHours:
partial class ProjectTask
{
...
public double TotalProcessHours { get { return ProjectBookings.Sum(b =>
b.ProcessHours); }}
...
}
Hours_TextChanged is:
private void Hours_TextChanged(object sender, TextChangedEventArgs e)
{
UpdateHoursValidity();
}
UpdateHoursValidity() just fades a Text Message below the actual textbox. It is not connected with the "broken" textbox in any way:
private void UpdateHoursValidity()
{
string key = IsInvalidHoursWarning ? "ShowWarningStoryboard" :
"HideWarningStoryboard";
var storyboard = FindResource(key) as Storyboard;
if(storyboard != null) storyboard.Begin();
}
So nothing fancy here either.
What I tried so far:
- removing the textbox, recompiling, adding the textbox again, recompiling -> same situation
Setting the Language property of the textbox specifically in xaml (Language=de-CH)
Setting the culture according to these tips:
how to set default culture info for entire c# application
Setting the culture according to this blogpost:
http://www.west-wind.com/weblog/posts/2009/Jun/14/WPF-Bindings-and-CurrentCulture-Formatting
There is NO Message on the debugconsole when I try to enter a ".".
Any ideas on this one?
Thanks in advance!

This is a fairly well known (and documented) issue relating to TextBox controls and data bound float values. You can fix this issue, by adding a StringFormat to your Binding:
<TextBox x:Name="_Hours" Grid.Row="9" Grid.Column="1" VerticalAlignment="Center"
TextAlignment="Center" FontWeight="Bold" FontSize="16" Text="{Binding ProcessHours,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, StringFormat={}{##.##}}"
TextChanged="Hours_TextChanged" />
Please adjust the format to suit your situation. You can find more formats in the Custom Numeric Format Strings post at MSDN.

There is a detailed discussion on the .NET 4.5 change that causes this issue on the Microsoft Connect site: https://connect.microsoft.com/VisualStudio/feedback/details/737301/binding-to-wpf-textbox-seems-to-be-broken-in-net-4-5-beta
In addition to the StringFormat workaround, another option is to set a Delay for the binding.

Related

Formatted Textboxes for UWP

I was wondering if anybody had any recommendations on how I could format a textbox for time inputs(hh:mm:ss) as well as Coordinates in Degrees,Minutes, Seconds (dd°mm'ss"). I am well aware that you can set the format of a string by the String.Format() method.... this does give me the desired layout in the textbox, but I want a control that has the appropriate symbols locked in and will autotab over those symbols as the user gives their inputs.
I have been searching for a way to do this in C#/UWP for a while with no luck, if anybody has any suggestions or could point me in the right direction it would be greatly appreciated.
The UWP Community Toolkit has some very good controls which are easy to integrate and one of them is the TextBox Mask control which is ideal for your scenario.
You can also try out the TextBoxRegex control which is not quiet what you want but is indeed something you should check out before proceeding.
Please reach out in case you are having difficulty in integrating the control for your specific requirement.
Optionally, you can download the sample app for the UWP toolkit to know about all the available controls /Tools. (UWP Community Toolkit Sample App)
EDIT 1:
As you might have noticed, the default behaviour for tab is that it sets the focus to the next control. Thus, having a single control will not be ideal since on press of tab, your textbox would lose focus and you would need to update the text and set the focus back to your textbox.
A relatively simpler way would be the following:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" BorderThickness="1">
<StackPanel.BorderBrush>
<SolidColorBrush Color="{ThemeResource SystemBaseHighColor}"/>
</StackPanel.BorderBrush>
<TextBox x:Name="hour" MaxLength="2" BorderBrush="{x:Null}" VerticalAlignment="Center" HorizontalAlignment="Center" LostFocus="hour_LostFocus"></TextBox>
<TextBlock Text=":" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
<TextBox x:Name="minute" MaxLength="2" BorderBrush="{x:Null}" HorizontalAlignment="Center" VerticalAlignment="Center" LostFocus="minute_LostFocus"></TextBox>
<TextBlock Text=":" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
<TextBox x:Name="second" MaxLength="2" BorderBrush="{x:Null}" HorizontalAlignment="Center" VerticalAlignment="Center" LostFocus="second_LostFocus"></TextBox>
</StackPanel>
This is basically your custom build control/usercontrol. So that when user tabs out it moves to the next textbox inside the stackpanel and so on.
In your hour_LostFocus event you can validate the textbox's current value and append 0 and do other validations .
private void hour_LostFocus(object sender, RoutedEventArgs e)
{
string val = (sender as TextBox).Text;
Regex regex = new Regex(#"^([0[0-9]|1[0-9]|2[0-3])$");
Match match = regex.Match(val);
if (!match.Success)
{
//append 0 and other validations
}
}
The same applies for minute and seconds .. just that the regex would be different in these cases.

How to set and get tag in xaml dynamically?

While creating GUI using xaml, I created a textbox with a tag like this:
<TextBox Name="TextBox" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="216,178,143,120" Width="158"
Tag="myTag"/>
Now I want to let the user be able to change this tag. For that, I am looking for a kind of function of form:
TextBox.SetTag( "User Provided Tag" )
So that the tag can be changed into this one:
<TextBox Name="TextBox" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="216,178,143,120" Width="158"
Tag="User Provided Tag"/>
After searching the internet for quite a while, I didn't come up with any practical solution. Could someone help? Thanks.
You can use a binding between two controls. Say a user is allowed to enter a tag value from a TextBox. You just bind the Tag of the second TextBox to a Text property of the first TextBox:
<TextBox Name="enterTagTextBox" />
<TextBox Name="getTagTextBox" Tag="{Binding ElementName=enterTagTextBox, Path=Text}"/>
To test it I added a Button in my XAML:
<Button Height="25" Click="Button_Click_1"/>
In code behind I just retrieve the tag value and display it like this:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
string text = this.getTagTextBox.Tag.ToString();
global::System.Windows.Forms.MessageBox.Show(text);
}
I think your problem may arise from you naming your TextBox, "TextBox". Try giving it a name that does not clash with the class name, like "txtMyTextBox".
Then you can do, txtMyTextBox.Tag = "User Provided Tag";.
Or you can bind to it as PiotrWolkowski suggests.
However, I would like to add, that it seems like there should be a cleaner way of achieving your desired behaviour. With the caveat that I don't know the details of what you are trying to implement.
I strongly suggest creating a ViewModel (see: MVVM Pattern) to hold the data you want users to be able to edit. Then use the bindings in WPF to display the data.
You would need to use the property element usage in order to set the Tag property in Extensible Application Markup Language (XAML) to anything other than an object with a known and built-in type converter, such as a string.

WPF formatting labels with StringFormat

I have a WPF application. I have some labels and some datagrids which are bound to some public properties. Some of these properties are numerical values.
In the datagrids I have been using the line below to ensure the values only display two decimal places, which works. However when I use the same line below for my label it appears to have no effect on the display as the number shows to about 9 decimal places. I don't understand why it works for the datagrid but not the label?
StringFormat={}{0:0.##}
<Label Grid.Row="3" Grid.Column="1"
Content="{Binding Obs.Tstat, StringFormat={}{0:0.#}}"
HorizontalAlignment="Center" Foreground="{StaticResource brushLinFont}"
FontSize="13" FontWeight="Bold"/>
Updated code
<Label Grid.Row="3" Grid.Column="1"
Content="{Binding Obs.Tstat}" ContentStringFormat="{}{0:0.#}}"
HorizontalAlignment="Center" Foreground="{StaticResource brushLinFont}"
FontSize="13" FontWeight="Bold"/>
For label you need to use ContentStringFormat:
<Label Content="{Binding Obs.Tstat}" ContentStringFormat="{}{0:0.##}"/>
Reason:
Label's Content property is of type object and StringFormat is used only when binding property is of type String.
If you try your code with TextBlock's Text property it will work fine with StringFormat because Text property is of type string.
Just a quick addition I'd like to post along these lines in case anyone else runs in to it... My application uses localization since it has multi-country support, but we also support user's system settings. We noticed ContentStringFormat defaults to your UI culture.
That caused an issue in one of our forms where the user's machine-specific decimal places they had configured in windows settings were not respected when you specified the ContentStringFormat.
Since the ContentPresenter simply takes the string format without the converter culture you could normally specify in the binding , this means that a format of say: 0:N will only return two decimal places if English is my current UI culture, even though I have 5 decimals specified on my windows settings.
In our case we applied some binding overrides to work around this, but mainly just wanted to add this extra bit of info in case anyone else runs in to it ;)

ComponentOne Silverlight numericbox maximum attribute not working correctly

I have a ComponentOne numericbox in Silverlight 5 and I want the range to be from 0.000000000 to 999.999999999. So I set the max and min accordingly but when I run the app it allows me to enter 1000.00000000. Anyone know why this is? Is there a way around this? He is my code in the xaml:
<c1:C1NumericBox SelectOnFocus="Always" x:Name="interestrateNumericbox"
AllowNull="True" Minimum="0.00000000" Maximum="999.99999999" Increment="0"
Format="N8" ShowButtons="False" RangeValidationMode="Always"
Value="{Binding Path=Model.InterestRate, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource NullableDoubleToDouble}}" Height="26"
HorizontalAlignment="Left" Width="308" VerticalAlignment="Bottom"
d:LayoutOverrides="Height" />
You are suggested to try using the latest build of the control and see if you still face any issues.
Next, a workaround for you is to set the maximum value again if the first digit entered is "1″. Following is the code for your reference :
void C1NumericBox1_ValueChanged(object sender, C1.Silverlight.PropertyChangedEventArgs<double> e)
{
if (e.NewValue == 1)
{
C1NumericBox1.Maximum = 999.99999999;
}
}

Bind textbox to float value. Unable to input dot / comma

When I try to input a DOT or a COMMA in a textbox, for example 1.02 or 83,33 the textbox prevents me to input such a value (and the input turns red). The textbox is bound to a float property. Why?
I have bound a textbox to a float Property Power of a class implementing INotifyPropertyChanged.
private float _power;
public float Power
{
get { return _power; }
set
{
_power = value;
OnPropertyChanged("Power");
}
}
In Xaml
<TextBox Name="txtPower" Height="23" TextWrapping="Wrap" Text="{Binding Path=Power, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
I have no custom validation at all right now.
Also tried decimal but it does not work either. For string everything works fine.
If you have .NET 4.5 or newer, you may enforce the pre 4.5 behaviour
System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;
See Sebastian Lux's blog:
With .NET 4.5 it is no longer possible to enter a separator character (comma or dot) with UpdateSourceTrigger = PropertyChanged by default. Microsoft says, this intended.
Try adding a StringFormat definition to the binding.
Like so:
<TextBox Name="txtPower" Height="23"
TextWrapping="Wrap" Text="{Binding Path=Power, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,StringFormat=N2}"></TextBox>
to fix dot and comma issue in textbox binding to decimal or float
1- UpdateSourceTrigger = LostFocus
2- add string format StringFormat={}{0:#.##} to escape unneeded zeros
<TextBox Name="txtPower" Height="23"
TextWrapping="Wrap" Text="{Binding Path=Power, Mode=TwoWay,
UpdateSourceTrigger=LostFocus ,StringFormat={}{0:#.##}}"></TextBox>

Categories

Resources