在列表框中select一个文本框项目不会更改列表框的选定项目

我有一个wpf列表框,显示一个文本框列表。 当我点击文本框时,列表框select不会改变。 我必须单击文本框旁边的select列表框项目。 是否有一些属性,我需要设置文本框转发点击事件到列表框?

一定要使用适当的TargetType:ListViewItem,ListBoxItem或TreeViewItem。

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

我们使用以下样式来设置一个PreviewGotKeyboardFocus,它处理TextBox控件和combobox的所有事件,例如:

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

然后我们select后面代码中的行:

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

我没有足够的代表发表评论,所以我张贴我的评论作为答案。 上面的Grazer解决scheme在您需要其他控件(如需要SelectedItemButton情况下不起作用。 这是因为按照Style Trigger ,当您单击该Button时, IsKeyboardFocusWithin将变为false,并且SelectedItem将变为null。

我用类似罗伯特的解决scheme,但没有代码(使用附加的行为)。

为此,

第一。 创build单独的课程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 } } 

第二。 在资源部分添加样式(我的样式在焦点上为黑色)。 注意FocusBehaviour.IsListBoxItemSelected属性的setter。 你应该在xmlns:behave="clr-namespace:MyBehaviours"引用它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> 

`

第三。 (可选,用于反向任务)

你会遇到,如果不是任何,反向任务 – 关注TextBox当ListBoxItem被选中。 我build议使用行为类IsFocused的另一个属性。 这里是ListBoxItem的示例模​​板,请注意Property="behave:FocusBehaviour.IsFocused"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> 

我使用类处理程序来设置此行为。 这样做将修复应用程序中的所有列表视图。 我不知道为什么这不是默认行为。

在您的App.xaml.cs中,将以下内容添加到OnStartup:

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

是否有一些属性,我需要设置文本框转发点击事件到列表框?

这不是一个简单的属性,但是您可以在TextBox上处理GotFocus事件,然后使用VisualTreeHelper来查找ListBoxItem并select它:

 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; } 

我已经能够find的最简单的方法是使用PreviewMouseDown事件并设置模板父级的IsSelected属性。 由于预览事件冒泡,ListBoxItem将在用户单击文本框,combobox或您设置事件的任何其他控件时立即处理该事件。

关于这一点的一个好处是,你可以使用相同的事件的所有types的控制,因为他们都来自框架元素。 此外,设置IsSelected(而不是设置SelectedItem)将导致您将列表框的SelectionMode设置为“Extended”时select多个项目,这可能会或可能不是您正在查找的内容。

即:

C#代码

 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"/> ... 

这是你正在寻找的答案: select一个ListBoxItem当其内部的combobox聚焦

列表框处理项目select,但不知道embedded文本框的焦点。 如果您想在文本框获得input焦点时更改select,则需要手动更改列表框选项afaik。

我不完全相信你会想要直接设置select,如前面的答案所述,因为我认为这将打破多选和其他一些scenerios

。 您可能想尝试重新设置下面的button,看看会发生什么。

 <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 /> 

你的初始情况不是很具体。 但我假设你使用DataBinding和ItemTemplate。 这是一个简单的方法来做到这一点,以及如果你的初学者在这个话题。 这应该工作:

 <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) */ } 

试试这个代码:

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

旧的讨论,但也许我的回答可以帮助别人….

Ben的解决scheme与Grazer的解决scheme有同样的问题。 坏的是,select取决于文本框的[键盘]焦点。 如果你的对话框有另一个控件(比如一个button),单击该button时焦点会丢失,并且listboxitem变为未选中状态(SelectedItem == null)。 所以你有不同的行为来点击项目(在文本框外)并点击文本框。 这是非常繁琐的处理,看起来很奇怪。

我很确定没有纯粹的XAML解决scheme。 我们需要代码隐藏。 解决scheme接近Mark的build议。

(在我的例子中,我使用ListViewItem而不是ListBoxItem,但解决scheme适用于两者)。

代码隐藏:

 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; } } 

与FindParent(取自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); } 

在我的DataTemplate中:

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

以下是@ Ben的答案的简化,而不必重写DataTemplate。 它甚至可以作为一个静态的风格应用。 使用包含GridView > GridViewColumn > TextBox的ListView进行testing。

例:

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