In my VS 2012 WPF project, I have a customized textbox class called TextBoxDX that adds an AutoSelect feature. No problem. I have another class based on TextBoxDX called IntBox which only allows integers. That’s where our story begins. Both classes are used in binding situations like so:
<local:TextBoxDX Grid.Row="0" Grid.Column="1" x:Name="txtBox_singlesName" Width="320" HorizontalAlignment="left" Text="{Binding SelectedItem.name, ElementName=listBoxSingles, Mode=OneWay}"/>
<local:IntBox x:Name="intBox_heightin" Width="60" AllowZeroValue="True" MaxLength="2" Text="{Binding SelectedItem.heightin, ElementName=listBoxSingles, Mode=OneWay}" MinVal="0" MaxVal="11"/>
Pretty sure most of that is irrelevant except for the binding. Both work fine in that they change their text corresponding to ListBox selections. But in the IntBox class, I had to add code for allowing only integers. In order to do that, I tapped into the TextChanged event in my IntBox class. The end result is this:
using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace Herculese
{
public class IntBox : TextBoxDX
{
//INIT PROPERTIES
private int _MaxVal = 0;
private int _MinVal = 0;
private bool _AllowZeroValue = false;
//INIT STRING TO KEEP TRACK OF TEXT BEFORE CHANGES
private string originalText;
public IntBox()
{
//ADD TO TEXTCHANGED HANDLER
TextChanged += new TextChangedEventHandler(My_OnTextChanged);
//STORE ORIGINAL TEXT
originalText = this.Text;
}
//EVENT HANDLER WHEN TEXT IS CHANGED
private void My_OnTextChanged(object sender, EventArgs e)
{
//IF THERE IS TEXT IN THE BOX,
MessageBox.Show("yee");
if (this.Text.Length > 0)
{
//REMOVE SPACES AND LEADING ZEROS FROM STRING
if (!_AllowZeroValue)
this.Text = this.Text.TrimStart('0');
this.Text = Regex.Replace(this.Text, @"\s+", "");
//IF VALUE ISN'T NUMERICAL OR NOTHING IS LEFT AFTER REMOVING ZEROS AND SPACES, CHANGE TEXT BACK TO ORIGINAL
Regex regex = new Regex("[^0-9]+");
if (regex.IsMatch(this.Text) || this.Text.Length < 1)
{
this.Text = originalText;
System.Media.SystemSounds.Beep.Play();
}
//IF VALUE IS NUMERICAL,
else
{
//MAKE SURE VALUE IS WITHIN ACCEPTED RANGE. IF NOT, CHANGE IT TO HIGHEST/LOWEST AVAILABLE RESPECTIVELY
int intText;
intText = Convert.ToInt32(this.Text);
if (intText > _MaxVal)
{
this.Text = _MaxVal.ToString();
System.Media.SystemSounds.Beep.Play();
}
else if (intText < _MinVal)
{
this.Text = _MinVal.ToString();
System.Media.SystemSounds.Beep.Play();
}
//SUCCESS! UPDATE ORIGINAL TEXT WITH NEW VALID VALUE.
else originalText = this.Text;
}
}
}
//PROVIDE GET/SET PROPERTIES
public int MaxVal
{
get { return _MaxVal; }
set { _MaxVal = value; }
}
public int MinVal
{
get { return _MinVal; }
set { _MinVal = value; }
}
public bool AllowZeroValue
{
get { return _AllowZeroValue; }
set { _AllowZeroValue = value; }
}
}
}
As you can see, I had a great time in the TextChanged of my IntBox. Wild parties, you name it. Suddenly I realized that binding for IntBox wasn’t working anymore. I could manually change the text just fine. It only accepted integers and worked like a charm. But changing the ListBox selection no longer updated the text. If I removed the code in My_OnTextChanged, the binding worked again. I figured my code was causing the problem. So I came back today with a fresh head and realized something weird.
If I remove the code in My_OnTextChanged and replace it with a MessageBox, the binding works and the message box appears. Makes perfect sense and furthers the idea that my code is causing the issue. Now for the weirdness: if I put the code back into the event after the MessageBox code, binding is broken again and the MessageBox never shows meaning the event never fires. All I can say to that is… HUUUUH?! I’ve recreated this several times just to be sure I’m not crazy. The only other thing I could think of is a conflict with the TextBoxDX that it inherits from so I made it inherit directly from TextBox and got the same results… Anybody got a clue on this one?
You are assigning a new value to
Textwhich is removing the original binding as you have replaced it with a new string.Instead of using
this.Text = "Somthing"try usingbase.SetCurrentValue(TextProperty, value);Example:
SetCurrentValueSets the value of a dependency property without changing its value source.