2009-03-17 13 views

Antwort

0

Die Listbox behandelt die Elementauswahl, kennt aber nicht den Fokus der darin eingebetteten Textbox. Wenn Sie die Auswahl jedes Mal ändern möchten, wenn ein Textfeld den Eingabefokus erhält, müssen Sie die Listenfeldauswahl manuell ändern, afaik.

2

Gibt es eine Eigenschaft ich für die Textbox festlegen muß das Click-Ereignis auf das Listenfeld zu übermitteln?

Es ist keine einfache Eigenschaft, aber Sie können die GotFocus Ereignis auf Ihrem TextBox, dann VisualTreeHelper die ListBoxItem und wählen Sie sie finden verwenden Griff:

private void TextBox_GotFocus(object sender, RoutedEventArgs e) 
{ 
    TextBox myTextBox = sender as TextBox; 
    DependencyObject parent = VisualTreeHelper.GetParent(myTextBox); 
    while (!(parent is ListBoxItem)) 
    { 
     parent = VisualTreeHelper.GetParent(parent); 
    } 
    ListBoxItem myListBoxItem = parent as ListBoxItem; 
    myListBoxItem.IsSelected = true; 
} 
0

ich nicht ganz sicher bin, würden Sie wollen, die Auswahl direkt zu setzen, wie in der vorherigen Antwort beschrieben, weil ich denke, es brechen würde Mehrfachauswahl und einige andere scenerios

. Sie können versuchen, eine Schaltfläche wie unten neu zu formatieren und zu sehen, was passiert.

<Button ClickMode="Pressed" Focusable="False"> 
<Button.Template> 
    <ControlTemplate> // change the template to get rid of all the default chrome 
     <Border Background="Transparent"> // Button won't be clickable without some kind of background set 
      <ContentPresenter /> 
     </Border> 
    </ControlTemplate> 
</Button.Template> 
<TextBox /> 

0

Ihre nicht sehr spezifisch über Ihre Ausgangssituation. Aber ich nehme an, dass Sie DataBinding und ein ItemTemplate verwenden. Thats imho eine einfache Möglichkeit, dies zu tun, auch wenn Ihr Anfänger zu diesem Thema. Dies sollte funktionieren:

<ListBox ItemsSource="{Binding someDataCollection}" Name="myListBox"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
     <TextBox Text="{Binding datafield}" Tag="{Binding .}" 
        GotFocus="TextBox_GotFocus"/> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

private void TextBox_GotFocus(object sender, RoutedEventArgs e) 
{ 
    myListBox.SelectedItem = (sender as TextBox).Tag; /* Maybe you need to cast to the type of the objects contained in the collection(bound as ItemSource above) */ 
} 
1

Der einfachste Weg, ich habe in der Lage gewesen zu finden, dies zu tun ist, um das Preview Ereignis zu verwenden und die IsSelected Eigenschaft der Templat-Eltern festgelegt. Da die Vorschau-Ereignisse nach unten blubbern, verarbeitet das ListBoxItem das Ereignis, sobald der Benutzer auf das Textfeld, die Combobox oder ein anderes Steuerelement klickt, auf dem Sie das Ereignis festlegen.

Eine schöne daran ist, dass Sie das gleiche Ereignis für alle Arten von Kontrollen verwenden können, da sie alle aus Rahmenelement abzuleiten. Wenn Sie IsSelected (statt SelectedItem) setzen, werden auch mehrere Elemente ausgewählt, wenn Sie den SelectionMode des Listenfelds auf "Extended" setzen, was das sein könnte, was Sie suchen.

dh:

C# -Code

private void Element_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    ((sender as FrameworkElement).TemplatedParent as ListBoxItem).IsSelected = true; 
} 

XAML

... 
    <ComboBox PreviewMouseDown="Element_PreviewMouseDown"/> 
    <TextBox PreviewMouseDown="Element_PreviewMouseDown"/> 
    ... 
34

Wir verwenden die folgenden Stil eine PreviewGotKeyboardFocus zu setzen, die alle Ereignisse von TextBox Steuergriffe und Comboboxen und so:

<ListView.ItemContainerStyle> 
     <Style TargetType="ListViewItem"> 
      <EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/> 
     </Style> 
    </ListView.ItemContainerStyle> 

Und dann wählen wir die Zeile im Code hinter:

protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e) 
    { 
     ListViewItem item = (ListViewItem) sender; 
     item.IsSelected = true; 
    } 
+2

Dies scheint auf jeden Fall die beste Methode. Ich habe eine tief verschachtelte Hierarchie, ListBoxen, die in anderen ListBoxen enthalten sind, und verschiedene Steuerelemente, die in diesen enthalten sind. Diese Methode funktioniert nur, weil sie nur das ListBoxItem und nicht das enthaltene Steuerelement verwendet. Eine vorgeschlagene Änderung obwohl - es ist einfacher, den Artikel direkt auszuwählen: item.IsSelected = true – Niall

+0

Ausgezeichneter Vorschlag! Ich habe den Code geändert .. – Arcturus

+2

Grazer hat eine bessere Antwort unter – Amsakanna

3

ich ähnlich wie Robert-Lösung verwendet, aber ohne Code hinter (mit beiliegendem Verhalten).

Um dies zu tun,

Zuerst. Erstellen Sie separate Klasse FocusBehaviour:


using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 

namespace MyBehaviours 
{ 
    public class FocusBehaviour 
    { 
     #region IsFocused 
     public static bool GetIsFocused(Control control) 
     { 
      return (bool) control.GetValue(IsFocusedProperty); 
     } 

     public static void SetIsFocused(Control control, bool value) 
     { 
      control.SetValue(IsFocusedProperty, value); 
     } 

     public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached(
      "IsFocused", 
      typeof(bool), 
      typeof(FocusBehaviour), 
      new UIPropertyMetadata(false, IsFocusedPropertyChanged)); 

     public static void IsFocusedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
     { 
      var control = sender as Control; 
      if (control == null || !(e.NewValue is bool)) 
       return; 
      if ((bool)e.NewValue && !(bool)e.OldValue) 
       control.Focus(); 
     } 

     #endregion IsFocused 

     #region IsListBoxItemSelected 

     public static bool GetIsListBoxItemSelected(Control control) 
     { 
      return (bool) control.GetValue(IsListBoxItemSelectedProperty); 
     } 

     public static void SetIsListBoxItemSelected(Control control, bool value) 
     { 
      control.SetValue(IsListBoxItemSelectedProperty, value); 
     } 

     public static readonly DependencyProperty IsListBoxItemSelectedProperty = DependencyProperty.RegisterAttached(
      "IsListBoxItemSelected", 
      typeof(bool), 
      typeof(FocusBehaviour), 
      new UIPropertyMetadata(false, IsListBoxItemSelectedPropertyChanged)); 

     public static void IsListBoxItemSelectedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
     { 
      var control = sender as Control; 
      DependencyObject p = control; 
      while (p != null && !(p is ListBoxItem)) 
      { 
       p = VisualTreeHelper.GetParent(p); 
      } 

      if (p == null) 
       return; 

      ((ListBoxItem)p).IsSelected = (bool)e.NewValue; 
     } 

     #endregion IsListBoxItemSelected 
    } 
} 

Sekunde. Fügen Sie einen Stil im Ressourcenbereich hinzu (mein Stil ist im Fokus schwarz gerundet). Benachrichtigungssetter für die FocusBehaviour.IsListBoxItemSelected-Eigenschaft. Sie sollten darauf verweisen in xmlns:behave="clr-namespace:MyBehaviours"

`

<Style x:Key="PreviewTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}"> 
     <Setter Property="BorderThickness" Value="1"/> 
     <Setter Property="Padding" Value="1"/> 
     <Setter Property="AllowDrop" Value="true"/> 
     <Setter Property="Background" Value="White"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type TextBox}"> 
        <Border 
         Margin="6,2,0,4" 
         BorderBrush="#FFBDBEBD" 
         BorderThickness="1" 
         CornerRadius="8" 
         Background="White" 
         VerticalAlignment="Stretch" 
         HorizontalAlignment="Stretch" 
         MinWidth="100" 
         x:Name="bg"> 
         <ScrollViewer 
          x:Name="PART_ContentHost" 
          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
        </Border> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsKeyboardFocusWithin" Value="True"> 
          <Setter Property="Background" TargetName="bg" Value="Black"/> 
          <Setter Property="Background" Value="Black"/><!-- we need it for caret, it is black on black elsewise --> 
          <Setter Property="Foreground" Value="White"/> 
          <Setter Property="behave:FocusBehaviour.IsListBoxItemSelected" Value="True"/> 
         </Trigger> 

        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

`

Dritter. (optional, für umgekehrte Aufgabe)

Sie werden, wenn nicht, eine Reverse-Aufgabe treffen - Fokussierung auf TextBox, wenn ListBoxItem ausgewählt wird. Ich empfehle, eine andere Eigenschaft der Verhaltensklasse IsFokussiert zu verwenden. Hier ist eine Beispielvorlage für ListBoxItem, beachten Sie bitte Property="behave:FocusBehaviour.IsFocused" und FocusManager.IsFocusScope="True"

<DataTemplate x:Key="YourKey" DataType="{x:Type YourType}"> 
      <Border 
      Background="#FFF7F3F7" 
      BorderBrush="#FFBDBEBD" 
      BorderThickness="0,0,0,1" 
      FocusManager.IsFocusScope="True" 
      x:Name="bd" 
      MinHeight="40"> 
       <TextBox 
        x:Name="textBox" 
        Style="{StaticResource PreviewTextBox}" 
        Text="{Binding Value}" /> 
     </Border> 
     <DataTemplate.Triggers> 
      <DataTrigger 
       Binding="{Binding IsSelected,RelativeSource={RelativeSource AncestorType=ListBoxItem}}" 
       Value="True"> 
       <Setter 
        TargetName="textBox" 
        Property="behave:FocusBehaviour.IsFocused" 
        Value="True" /> 
      </DataTrigger> 
     </DataTemplate.Triggers> 
    </DataTemplate> 
3

ich eine Klasse Handler dieses Verhalten einzustellen. Auf diese Weise werden alle Listenansichten in der Anwendung korrigiert. Ich weiß nicht, warum das nicht das Standardverhalten ist. Folgendes OnStartup

In Ihrem App.xaml.cs hinzu:

protected override void OnStartup(StartupEventArgs e) 
    { 
     EventManager.RegisterClassHandler(typeof (ListViewItem), 
              ListViewItem.PreviewGotKeyboardFocusEvent, 
              new RoutedEventHandler((x,_) => (x as ListViewItem).IsSelected = true)); 
    } 
37

Achten Sie darauf, geeignete Target zu verwenden: ListViewItem, ListBoxItem oder TreeViewItem.

<Style TargetType="ListViewItem"> 
    <Style.Triggers> 
     <Trigger Property="IsKeyboardFocusWithin" Value="true"> 
      <Setter Property="IsSelected" Value="true" /> 
     </Trigger> 
    </Style.Triggers> 
</Style> 
+1

Funktioniert nicht, wenn existiert bereits. – ender

+1

Dies hat auch das Problem, dass die Auswahl entfernt wird, wenn der ListView den Fokus verliert. Die Antwort unten ist besser von Arcturus –

0

Versuchen Sie diesen Code:

foreach (object item in this.listBox1.Items) { 
    if (textbox1.text.equals(item.toString())) { 
     //show error message; break 
    } 
} 
6

ich nicht kommentieren genug Wiederholungen müssen, so dass ich meinen Kommentar als Antwort veröffentlichen. Die obige Grazer-Lösung funktioniert nicht in Fällen, in denen Sie ein anderes Steuerelement haben, z. B. Button, das SelectedItem benötigt. Dies liegt daran, dass gemäß Style Trigger die IsKeyboardFocusWithin falsch wird, wenn Sie auf Button klicken, und die SelectedItem wird null.

0

alte Diskussion, aber vielleicht meine Antwort hilft anderen ....

Ben-Lösung hat das gleiche Problem wie Grazers Lösung. Das Schlimme ist, dass die Auswahl vom [Tastatur-] Fokus der Textbox abhängt. Wenn Sie ein anderes Steuerelement in Ihrem Dialogfeld haben (z. B. eine Schaltfläche), geht der Fokus verloren, wenn Sie auf die Schaltfläche klicken, und das Listenfeld wird nicht ausgewählt (SelectedItem == null). Sie haben also ein anderes Verhalten, wenn Sie auf das Element (außerhalb des Textfelds) klicken und in das Textfeld klicken. Dies ist sehr mühsam zu handhaben und sieht sehr seltsam aus.

Ich bin mir ziemlich sicher, dass es dafür keine reine XAML-Lösung gibt. Dafür brauchen wir Code-Behind. Die Lösung kommt dem nahe, was Mark vorgeschlagen hat.

(in meinem Beispiel verwende ich ListViewItem statt ListBoxItem, aber die Lösung funktioniert für beide).

-Code-behind:

private void Element_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
    { 
     var frameworkElement = sender as FrameworkElement; 
     if (frameworkElement != null) 
     { 
      var item = FindParent<ListViewItem>(frameworkElement); 
      if (item != null) 
       item.IsSelected = true; 
     } 
    } 

mit FindParent (aus http://www.infragistics.com/community/blogs/blagunas/archive/2013/05/29/find-the-parent-control-of-a-specific-type-in-wpf-and-silverlight.aspx):

public static T FindParent<T>(DependencyObject child) where T : DependencyObject 
    { 
     //get parent item 
     DependencyObject parentObject = VisualTreeHelper.GetParent(child); 

     //we've reached the end of the tree 
     if (parentObject == null) return null; 

     //check if the parent matches the type we're looking for 
     T parent = parentObject as T; 
     if (parent != null) 
      return parent; 

     return FindParent<T>(parentObject); 
    } 

In meinem Datatemplate:

<TextBox Text="{Binding Name}" 
     PreviewMouseDown="Element_PreviewMouseDown"/> 
1

Das Folgende ist eine Vereinfachung der @ Ben Antwort ohne das DataTemplate zu überschreiben. Es kann sogar als statischer Stil angewendet werden. Getestet mit einer ListView, die eine GridView > GridViewColumn > TextBox enthält.

Beispiel:

<ListView.Resources> 
    <Style TargetType="{x:Type ListViewItem}"> 
     <Style.Triggers> 
      <Trigger Property="IsKeyboardFocusWithin" Value="True"> 
       <Setter Property="IsSelected" Value="True"></Setter> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</ListView.Resources> 
Verwandte Themen