Laden...

Forenbeiträge von Xalir Ingesamt 9 Beiträge

29.03.2013 - 20:50 Uhr

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.

27.03.2013 - 13:49 Uhr

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

27.03.2013 - 13:23 Uhr

Mir ist keine andere Methode bekannt, die es besser löst. Und es gibt auch keine unterschiedlichen Events dafür. Beim Multithreading könnte dies helfen


private void MethodWhichFiresEvents (Action myAction)
{
    IsManualFired = true;

    myAction();

    IsManualFired = false;
}

private void DoStuff()
{
    MethodWhichFiresEvents(() =>
    {
        cmbList.Children.Add(new ComboBoxItem());
    });
}
27.03.2013 - 12:56 Uhr

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).

27.03.2013 - 12:22 Uhr

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.

27.03.2013 - 12:09 Uhr

Ich verstehe noch nicht so ganz Dein Problem. Soweit ich das sehe, benötigst Du keinen Style, da Du das Aussehen des Controls nicht änderst. Daher könntest Du auf Styles verzichten und direkt das ControlTemplate als Ressource nutzen und einen x:Key vergeben.

Falls Du doch weiterhin das Aussehen verändern willst, was spricht denn dagegen


<Application.Resources>
    <ControlTemplate x:Key="MyContextMenuTemplate">
        <ContextMenu Style="myStyle" />
    </ControlTemplate>
    <Style TargetType="ContextMenu" x:Key="myStyle">
        <!-- Hier Deine Style-Änderungen -->
    </Style>
</Application.Resources>

Alternativ geht auch noch C#-Code direkt in XAML einzubetten. Da ich das ganze aus dem Kopf jetzt nicht zusammenkriege, verweise ich da auf Google.

27.03.2013 - 11:49 Uhr

Ich mache solche Sachen meist über eine Klassenvariable. Zum Beispiel


bool IsManualFired;

private myMethod()
{
    IsManualFired = true;

    //hier der Code um die ComboBox zu manipulieren

    IsManualFired = false;
}

Dann halt in Deiner SelectionChanged-Methode prüfen, ob die Variable true oder false ergibt und darauf dann entsprechend reagieren.

27.03.2013 - 02:16 Uhr

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?

27.03.2013 - 00:49 Uhr

Hallo m.grauber,

da ich gerade an etwas ähnlichem arbeite, kann ich Dir denke ich helfen.

Mit den Triggers kannst Du so direkt keinen Code-Behind ausführen lassen. Was Du aber machen kannst, ist folgendes

In App.xaml


<Application.Resources>
    <ControlTemplate x:Key="MyContextMenuTemplate">
        <ContextMenu />
    </ControlTemplate>
</Application.Resources>

In Deiner Code-Behind


var myContextMenu = (Application.Current.Resources["MyContextMenuTemplate"] as ControlTemplate).LoadContent() as ContextMenu;

myContextMenu.Loaded += ContextMenu_Loaded;

Hoffe, das hilft