Erratic behavior of TextBox "TextChanged" event

mauede 221 Reputation points

I have inserted in the GUI a TextBox. It must hold a number between 0 and 1 that represents a lower threshold for accepting a structure name guessed
by the Dice coefficient. I have set a default but the user can edit the threshold. Therefore I have to check the number entered is between 0 and 1.
The TextBox is implemented as follows:

TextBox TextChanged event:
<TextBox x:Name="DiceTol" Grid.Column="1" HorizontalAlignment="Left" Margin="655,0,0,0" Grid.Row="1" Text="{Binding DiceThreshold , Mode=TwoWay}" VerticalAlignment="Bottom"
Background="Wheat" FontFamily="Arial Black" FontWeight="Bold" FontSize="20" Width="100" Height="46" Grid.RowSpan="1" TextChanged="DiceTol_TextChanged" TargetUpdated="DiceTol_TargetUpdated" TextInput="DiceTol_TextInput"/>

I developed the code that checks the newly entered number using three different pre-existent TextBox events., namely, "TextChanged", "TargetUpdated", TextInput".
The only event that is triggered is "TextChanged" but it does not work all the times a new number is entered in the TextBox. During the debugging session
first, I erase the default value and then I type in a new value that is on purpose greater than 1 but the "TextChange" event is not triggered. Sometimes it is triggered when I click on a GUI button. The other two events are never triggered.

Here is the code I developed to check the number entered in the TextBox:

private void DiceTol_TextChanged(object sender, TextChangedEventArgs e)
if(DiceThreshold < 0 | DiceThreshold > 1)
MessageBox.Show("Please, enter a number between 0 and 1", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning);
DiceThreshold = DiceThresholdDefault;
DiceTol.Text = DiceThresholdDefault.ToString();

I would appreciate your help in fixing the above-illustrated problem.
Thank you

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,694 questions
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,481 questions
{count} votes

3 answers

Sort by: Most helpful
  1. Hui Liu-MSFT 46,961 Reputation points Microsoft Vendor

    For the problem of validating the bound data, you could refer to the following code.


    public partial class MainWindow : Window  
        public double DiceThreshold { get;set;}= 0.3;  
        public MainWindow()  
    public class DoubleRangeRule : ValidationRule  
            public double Min { get; set; }  
            public double Max { get; set; }  
            public override ValidationResult Validate(object value,   CultureInfo cultureInfo)  
              double parameter = 0;  
                if (((string)value).Length > 0)  
                  parameter = Double.Parse((String)value);  
              catch (Exception e)  
                return new ValidationResult(false, "Illegal characters or "    + e.Message);  
              if ((parameter < this.Min) || (parameter > this.Max))  
                return new ValidationResult(false,  
                    "Please enter value in the range: "  
                    + this.Min + " - " + this.Max + ".");  
              return new ValidationResult(true, null);  


            <local:DoubleRangeRule x:Key="DoubleRangeRule"/>  
            <Style x:Key="textBoxInError" TargetType="{x:Type TextBox}">  
                    <Trigger Property="Validation.HasError" Value="true">  
                        <Setter Property="ToolTip"  Value="{Binding RelativeSource={x:Static RelativeSource.Self},  Path=(Validation.Errors)/ErrorContent}"/>  
            <ControlTemplate x:Key="validationTemplate">  
                    <TextBlock Foreground="Red" FontSize="20">!</TextBlock>  
        <TextBox x:Name="DiceTol"    Background="Wheat" Width="100" Height="46"  Validation.ErrorTemplate="{StaticResource validationTemplate}"   Style="{StaticResource textBoxInError}">  
                        <Binding Path="DiceThreshold" StringFormat="N2"  UpdateSourceTrigger="PropertyChanged">  
                                <local:DoubleRangeRule Min="0.0" Max="1.0"/>  

    The result:



    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. mauede 221 Reputation points

    Thank you for the very sophisticated solution.
    I wonder whether I can use "Mode=TwoWay" in the binding statement for DiceThreshold. The code needs to use the entered value when it is within the established range.

  3. mauede 221 Reputation points

    Thank you very much. I got that TextBox working on adopting a simpler solution. Basically, I check the TextBox content when a Button is clicked launching the code stub that uses the TextBox content. If the TextBox numerical content falls outside the range a messageBox alerts the user and the TextBox content is set back to a default value.

    However, now I am facing a new challenge and wonder whether the code you sent me could be adapted to my new task.
    In MainWindow.XAML I have a ListBox that is used to display a list of strings that can be edited:

    ** <ListBox x:Name="EditableStructs" Grid.Row="5" Grid.Column="1" Margin="930,62,0,40" SelectionMode="Single" Grid.ColumnSpan="2" Background="PowderBlue" Height="500"
    ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.CanContentScroll="True" ItemsSource="{Binding AutoNames,Mode=TwoWay}" HorizontalAlignment="Left" Width="220" >
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="*"/>
    <TextBlock Name="TextInd" Text="{Binding NamInd, Mode=OneWay}" Grid.Column="0" Padding="1,5" HorizontalAlignment="Stretch"/>
    <CheckBox IsChecked="{Binding IsAccepted, Mode=TwoWay}" Grid.Column="1" Padding="5,5" VerticalAlignment="Center" HorizontalAlignment="Center" />
    <TextBox Text="{Binding StrName, Mode=TwoWay}" Grid.Column="2" HorizontalAlignment="Stretch"/>

    The code-behind in MainWindow.XAML.cs I populate the above ListBox upon clicking a Button:

    • public class EditableStructures
      public int NamInd { get; set; } = new int();
      public bool IsAccepted { get; set; } = new bool();
      public string StrName { get; set; } = "";
      public static List<EditableStructures> AutoNames { get; set; } = new List<EditableStructures>();***
    • PTAccess pt = new PTAccess();
      List<string> EditedList = new List<string>();
      EditedList = pt.StructuresAutomaticRename(structures);
      int j = 1;
      foreach (string str in EditedList)
      AutoNames.Add(new EditableStructures { StrName = str, IsAccepted = false, NamInd = j});
      // string DbgList = "" ; // DEBUG PURPOSE
      // DbgList = String.Join(" , ", AutoNames.Select(x => x.StrName)); // DEBUG PURPOSE
      //............................ Compare Number of Guessed Structure Names With Number Of Structure Names From Velocity DataBase
      // ............................ Alert User If Less Than 50% Structures Could Not Be Guessed
      int NumGuessed = 0;
      int NumOriginal = 0;
      var Guessed = AutoNames.Where(m => !string.IsNullOrWhiteSpace(m.StrName)).ToList();
      NumGuessed = Guessed.Count;
      NumOriginal = strucNames.Count;
      MessageBox.Show($" {NumGuessed} structures automatically renamed out of {NumOriginal} patient structures\n", "Is this patient belonging to this trial? ", MessageBoxButton.OK, MessageBoxImage.Information);

    *public void UpdateAutoStrucNames()
    EditableStructs.ItemsSource = (System.Collections.IEnumerable)AutoNames;

    Some of the ListBox items contain strings that have been "guessed" through the dice coefficient. The code knows the indexes of the items containing "guessed" strings.
    My questions:
    How can I draw the user's attention to such ListBox elements? Maybe changing their background color or showing the red "!" symbol as you implemented, or some other way.

    I would appreciate some help.
    Thank you in advance.