2009-05-18 10 views
2

J'ai un TextBox et un contrôle Popup. Je souhaite que la propriété Popup.IsOpen soit liée à la propriété TextBox.IsFocused. En d'autres termes, si la zone de texte a le focus, la fenêtre contextuelle est ouverte. Sinon, si la fenêtre contextuelle est active, je ne veux pas qu'elle se ferme en raison de la perte de focus du champ de texte. J'espérais gérer cela en utilisant des liaisons plutôt que d'avoir à faire face à cela dans les gestionnaires d'événements. Aussi, dois-je faire quelque chose concernant les propriétés de dépendance, puisqu'elles sont préexistantes (c'est-à-dire, enregistrer, remplacer les métadonnées, etc.), ou puis-je simplement lier à ces propriétés.La zone de texte de liaison est mise au point sur Popup IsOpen plus les conditions supplémentaires

Voici quelques exemples de code similaire à mon scénario

StackPanel sp = new StackPanel(); 
TextBox tb = new TextBox(); 
Popup popup = new Popup(); 

sp.Children.Add(tb); 
sp.Children.Add(popup); 
this.Content = sp; 

Binding bd = new Binding("IsFocused"); 
bd.source = tb.IsFocused; 
popup.SetBinding(Popup.IsOpenProperty, bd); 

A partir de ce que je suppose que si je clique sur le contrôle de la zone de texte et lui a donné l'accent, que la fenêtre contextuelle ouvrirait, et inversement, si la zone de texte perdu focus, que le popup se ferme. Je n'arrive pas à faire marcher ça. Si quelqu'un a une idée de ce que je fais de mal, alors peut-être pourrait-il aussi répondre à la seconde moitié de ma question que si la zone de texte perd son focus mais que c'est le popup qui reçoit le focus, ou redonner la priorité à la zone de texte pour qu'elle reste ouverte bc de la première liaison. Tout autre contrôle qui obtient un focus lorsque la zone de texte perd le focus ne s'applique pas à ce scénario.

Si je pouvais le reformuler pour plus de clarté, je le dirais comme ceci.

1.) Bind Popup.IsOpen à TextBox.IsFocused

2.) Bind TextBox.IsFocused à Popup.IsFocused (en supposant que cela va juste donner focus sur la zone de texte)


Voici mon premier C# tenter cela. Quelque chose ne va toujours pas bien. Rien ne se passe donc je ne sais pas trop où est mon erreur.

 StackPanel sp = new StackPanel(); 
     TextBox tb = new TextBox(); 
     Popup popup = new Popup(); 

     TextBox popupTextBox = new TextBox(); 
     popup.Child = popupTextBox; 


     sp.Children.Add(tb); 
     sp.Children.Add(popup); 
     this.Content = sp; 


     //***Questions concerning giving the UIElement a name and registering it 
     tb.Name = "siblingTextBox"; 
     System.Windows.NameScope.GetNameScope(tb).RegisterName("siblingTextBox", tb); 

     //***Questions concerning giving the UIElement a name and registering it 
     popupTextBox.Name = "popupTextBox"; 
     System.Windows.NameScope.GetNameScope(tb).RegisterName("popupTextBox", popupTextBox); 

     Binding binding = new Binding(); 
     binding.ElementName = tb.Name; 
     popup.PlacementTarget = tb; 

     Style style = new Style(); 
     style.TargetType = typeof(Popup); 

     DataTrigger dataTrigger = new DataTrigger(); 
     Binding focusedBinding = new Binding("IsFocused"); 
     focusedBinding.ElementName = tb.Name; 
     dataTrigger.Value = true; 
     dataTrigger.Binding = focusedBinding; 

     Setter setter = new Setter(); 
     setter.Property = Popup.IsOpenProperty; 
     setter.Value = true; 
     dataTrigger.Setters.Add(setter); 
     style.Triggers.Add(dataTrigger); 

     dataTrigger = new DataTrigger(); 
     focusedBinding = new Binding("IsFocused"); 
     focusedBinding.ElementName = popupTextBox.Name; 
     dataTrigger.Value = true; 
     dataTrigger.Binding = focusedBinding; 
     setter = new Setter(); 
     setter.Property = Popup.IsOpenProperty; 
     setter.Value = true; 
     dataTrigger.Setters.Add(setter); 
     style.Triggers.Add(dataTrigger); 

     popup.Style = style; 

Répondre

3

Le code suivant montre ayant deux zones de texte dans un StackPanel, la mise en focus sur la zone de texte du haut ouvrira la fenêtre contextuelle. À ce stade, si vous déplacez Focus dans la zone de texte contenue dans le menu contextuel, il restera ouvert. Si vous déplacez le focus sur un autre élément, dans ce cas la deuxième zone de texte dans le StackPanel, le Popup se fermera. Comme vous ne parvenez pas à focaliser le Popup lui-même, je suis en fait lié à la propriété IsFocused de la zone de texte dans le Popup.

<StackPanel> 
    <TextBox x:Name="text" Text="This is a text box" /> 
    <TextBox Text="Another Text Box" /> 
    <Popup PlacementTarget="{Binding ElementName=text}"> 
     <Popup.Style> 
      <Style TargetType="{x:Type Popup}"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding ElementName=text, Path=IsFocused}" Value="True"> 
         <Setter Property="IsOpen" Value="True" /> 
        </DataTrigger> 
        <DataTrigger Binding="{Binding ElementName=popupText, Path=IsFocused}" Value="True"> 
         <Setter Property="IsOpen" Value="True" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Popup.Style> 
     <TextBox x:Name="popupText" Text="HELLO WORLD" /> 
    </Popup> 
</StackPanel> 

Pour réaliser la même chose en C# vous ne devez pas utiliser les liaisons elementName que vous avez déjà les éléments à portée de main. J'utilise presque toujours XAML pour définir mes éléments, donc je suis sûr que vous pouvez ranger ça un peu.

var text1 = new TextBox { Name = "text", Text = "This is a text box" }; 
var text2 = new TextBox { Text = "Another Text Box" }; 
var popupText = new TextBox { Name = "popupText", Text = "HELLO WORLD" }; 
var popup = new Popup { Child = popupText, PlacementTarget = text1 }; 
var stackPanel = new StackPanel(); 

stackPanel.Children.Add(text1); 
stackPanel.Children.Add(text2); 
stackPanel.Children.Add(popup); 

var popupStyle = new Style(typeof (Popup)); 
var textIsFocusedTrigger = new DataTrigger 
    { 
     Binding = new Binding {Source = text1, Path = new PropertyPath("IsFocused")}, 
     Value = true 
    }; 

textIsFocusedTrigger.Setters.Add(new Setter(Popup.IsOpenProperty, true)); 

var popupTextIsFocusedTrigger = new DataTrigger 
    { 
     Binding = new Binding {Source = popupText, Path = new PropertyPath("IsFocused")}, 
     Value = true 
    }; 

popupTextIsFocusedTrigger.Setters.Add(new Setter(Popup.IsOpenProperty, true)); 

popupStyle.Triggers.Add(textIsFocusedTrigger); 
popupStyle.Triggers.Add(popupTextIsFocusedTrigger); 

popup.Style = popupStyle; 

J'espère que cela aide!

+0

Cela semble être très proche de ce que je veux faire. J'ai couru votre code dans une application de test et le comportement est très similaire. J'ai écrit le C# pour faire ce que fait votre xaml, mais quelque chose est toujours éteint. Comme je n'utilise pas XAML, je pense que j'ai des problèmes avec la liaison à ElementName. Dois-je simplement définir la propriété Name ou enregistrer le nom. Ci-dessous vous verrez ce que j'ai jusqu'ici, laissez-moi savoir si vous pouvez voir ce qui pourrait être faux. Merci beaucoup. – BrandonS

+0

Je viens d'éditer ma réponse pour fournir une version C# de ce que je faisais en XAML, j'espère que c'est ce dont vous avez besoin. Par intérêt, pourquoi utilisez-vous C# sur XAML pour créer vos éléments? –