Laden...

TextBox.Focus() führt zu einer StackOverflowException

Erstellt von Xalir vor 11 Jahren Letzter Beitrag vor 11 Jahren 3.143 Views
X
Xalir Themenstarter:in
9 Beiträge seit 2013
vor 11 Jahren
TextBox.Focus() führt zu einer StackOverflowException

Hallo,

ich habe in einer WPF-Anwendung eine TextBox, die validiert werden muss. Die Validierung soll stattfinden, sobald die TextBox den Fokus verliert und mit txt.Focus() und txt.SelectAll() der fehlerhafte Inhalt markiert werden.

Soweit so gut, in meiner Anwendung ist das nachfolgende Control eine ComboBox. Wenn ich jetzt eine fehlerhafte Eingabe provoziere, führt der Fokus zu einer StackOverflowException, da die ComboBox jedesmal sich den Fokus wiederholt.

Hier die Controlvorlage:

<ControlTemplate x:Key="SplitTemplate">
  <Expander IsExpanded="True" IsTabStop="False">
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>
      <Label />
      <TextBox Grid.Column="1" />
      <Label Grid.Row="1" Content="Rassenrestriktion" />
      <ComboBox Grid.Column="1" Grid.Row="1" SelectedIndex="0"
            ItemsSource="{Binding Source={StaticResource Races}, XPath=Race/Language}" />
      <Label Grid.Row="2" Content="Rollenrestriktion" />
      <ComboBox Grid.Column="1" Grid.Row="2" SelectedIndex="0"
            ItemsSource="{Binding Source={StaticResource Roles}, XPath=Role}" />
      <Label Grid.Row="3" Content="Attributsrestriktion" />
      <ComboBox Grid.Column="1" Grid.Row="3" Name="cmbGeneralAttributeRestriction1" SelectedIndex="0"
            ItemsSource="{Binding Source={StaticResource Attributes}, XPath=Attribute}" />
    </Grid>
  </Expander>
</ControlTemplate>

Ich lade die Controlvorlage und weise der TextBox ein LostFocus-EventHandler zu.

Mein EventHandler sieht so aus

private void txt_LostFocus(object sender, RoutedEventArgs e)
{
    var txt = sender as TextBox;
    int UnitsInSplit;
    int TotalUnits;
    bool IsGeneral;
    StackPanel pnl;
            
    if(txt.Text.Length==0)
    {
        return;
    }

    int.TryParse(txt.Text, out UnitsInSplit);

    if ((((txt.Parent as Grid).Parent as Expander).Parent as StackPanel)
        .Name.Contains("General"))
    {
        int.TryParse(txtGenerals.Text, out TotalUnits);
        pnl = pnlGeneralSplit;
        IsGeneral = true;
    }
    else
    {
        int.TryParse(txtTroops.Text, out TotalUnits);
        pnl = pnlTroopSplit;
        IsGeneral = true;
    }

    var Position = pnl.Children.IndexOf((txt.Parent as Grid).Parent
        as Expander);

    if (UnitsInSplit > TotalUnits)
    {
        txt.Focus();
        txt.SelectAll();
    }

    if (UnitsInSplit < TotalUnits && Position == pnl.Children.Count - 1)
    {
        CreateNewSplit(pnl, IsGeneral);
        return;
    }            
}

Ich habe zumindest das Problem soweit eingrenzen können, dass es auftritt, wenn ich mit der Tastatur navigiere. Wechsle ich den Fokus mit der Maus, tritt keine StackOverflowException auf. Hat jemand eine Idee, woran dies liegt und wie ich den Fehler beheben kann?

5.657 Beiträge seit 2006
vor 11 Jahren

Hi Xalir,

das könntest du aber sehr einfach selbst herausfinden, indem du einen Breakpoint in die Methode setzt und mit Einzelschritt-Debugging durchgehst, um zu schauen, was passiert. Im Stacktrace der Exception stehen auch die Methodenaufrufe drin, da siehst du bestimmt, daß es sich um rekursive Aufrufe handelt.

Christian

Weeks of programming can save you hours of planning

X
Xalir Themenstarter:in
9 Beiträge seit 2013
vor 11 Jahren

Hi MrSparkle,

Einzelschritt-Debugging habe ich gemacht. Der StackTrace erzählt mir folgendes: "Der Ausdruck kann nicht ausgewertet werden, weil sich der Thread in einem Stapelüberlauf befindet."

Zu Debugging-Zwecken habe ich bei der ComboBox ein GotFocus-Event hinzugefügt. Nun weiß ich zwar, dass etwas schief läuft, aber ich komme dennoch nicht weiter. Wie gesagt, die Exception wird nur dann gefeuert, wenn ich über die Tab-Taste navigiere. Mit der Maus gibt es keine Probleme.

5.657 Beiträge seit 2006
vor 11 Jahren

Einzelschritt-Debugging habe ich gemacht.

Dann weißt du ja jetzt, wie der Programm-Ablauf ist, bevor die Exception eintritt.

Nun weiß ich zwar, dass etwas schief läuft

...behältst es aber für dich 🤔

aber ich komme dennoch nicht weiter.

Wo genau kommst du nicht weiter? Was genau ist das Problem?

Weeks of programming can save you hours of planning

X
Xalir Themenstarter:in
9 Beiträge seit 2013
vor 11 Jahren

Dann weißt du ja jetzt, wie der Programm-Ablauf ist, bevor die Exception eintritt.

Ablauf ist wie folgt:

txt_LostFocus wird ausgelöst beim Verlassen des Fokus. Es geht in den von mir geposteten Programmteil. Die Überprüfung findet statt, txt.Focus() und txt.SelectAll() wird ausgeführt. Sobald dass passiert, tritt ComboBox_GotFocus ein und txt_LostFocus wird wieder ausgeführt. Somit führt es zur Endlosschleife.

Zwischen den beiden Ereignissen wird kein weiterer Code ausgeführt, der Debugger springt sofort wieder nach txt_LostFocus.

Wo genau kommst du nicht weiter? Was genau ist das Problem?

Das Problem ist, die ComboBox holt sich aus Gründen, die ich nicht kenne und wo ich das Problem nicht näher eingrenzen kann, den Fokus immer und immer wieder. Kein Programmcode von meiner Seite löst das Ereignis aus. Ich möchte herausfinden, was denn das GotFocus-Ereignis auslöst (Abgesehen von dem einmaligen Fokus setzen über die Tab-Navigation).

5.657 Beiträge seit 2006
vor 11 Jahren

Das Problem ist, die ComboBox holt sich aus Gründen, die ich nicht kenne und wo ich das Problem nicht näher eingrenzen kann, den Fokus immer und immer wieder.

Weil du es so programmiert hast:

Die Überprüfung findet statt, txt.Focus() und txt.SelectAll() wird ausgeführt. Sobald dass passiert, tritt ComboBox_GotFocus ein und txt_LostFocus wird wieder ausgeführt.

Wenn du im LostFocus-EventHandler die Focus-Methode aufrufst, dann ist es alles andere als verwunderlich, daß die Textbox den Focus bekommen, oder?

Christian

Weeks of programming can save you hours of planning

X
Xalir Themenstarter:in
9 Beiträge seit 2013
vor 11 Jahren

Anscheinend stehe ich auf den Schlauch, denn ich verstehe Deine Aussage nicht. Die TextBox soll ja den Fokus wiederbekommen, wenn eine Fehleingabe auftritt. Aber was hat der Fokus der TextBox mit dem Fokus der ComboBox zu tun? Ich verweise ja auf die TextBox und nicht auf die ComboBox.

Edit: Ja, ja jetzt macht Deine Aussage Sinn. Ja, Du hast recht. Ich bin in meinem Denken gefangen gewesen. Jetzt fällt es mir wie Schuppen vor die Augen

X
Xalir Themenstarter:in
9 Beiträge seit 2013
vor 11 Jahren

So, nach etlichen Hin und Her bin ich jetzt zur Lösung gekommen. Es lag nicht an einer falschen Programmierung.


txt.SelectAll();
Application.Current.Dispatcher.BeginInvoke(new Action(() => txt.Focus()));

Dies löst mein Problem mit der Endlosschleife.

C
252 Beiträge seit 2007
vor 11 Jahren

Trotzdem solltest du nicht mehrere Foren gleichzeitig "belästigen". siehe [Hinweis] Wie poste ich richtig? 2.2
Crosspost