2009-03-17 95 views

Trả lời

0

Hộp danh sách xử lý lựa chọn mục nhưng không biết về trọng tâm của hộp văn bản được nhúng bên trong. Nếu bạn muốn thay đổi lựa chọn bất cứ khi nào một hộp văn bản được tập trung đầu vào thì bạn cần phải thay đổi lựa chọn hộp danh sách theo cách thủ công, afaik.

2

Có một số thuộc tính tôi cần đặt cho Hộp văn bản để chuyển tiếp sự kiện nhấp vào Hộp danh sách không?

Nó không phải là một tài sản đơn giản, nhưng bạn có thể xử lý các sự kiện GotFocus trên TextBox của bạn, sau đó sử dụng VisualTreeHelper để tìm ListBoxItem và chọn nó:

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

Tôi không hoàn toàn chắc chắn rằng bạn muốn để thiết lập lựa chọn trực tiếp như được mô tả trong câu trả lời trước bởi vì tôi nghĩ rằng nó sẽ phá vỡ đa lựa chọn và một số scenerios khác

. Bạn có thể muốn thử tạo lại một nút như dưới đây và xem điều gì sẽ xảy ra.

<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

không bạn rất cụ thể về tình hình ban đầu của bạn. Nhưng tôi cho rằng bạn sử dụng DataBinding và một ItemTemplate. Đó là một cách dễ dàng để làm điều này, cũng như nếu người mới bắt đầu của bạn về chủ đề này. Điều này sẽ làm việc:

<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

Cách đơn giản nhất tôi đã có thể tìm thấy để làm điều này là sử dụng sự kiện PreviewMouseDown và thiết lập thuộc tính của cha mẹ templated IsSelected. Kể từ khi sự kiện xem trước bong bóng xuống, ListBoxItem sẽ xử lý sự kiện ngay sau khi người dùng nhấp vào hộp văn bản, combobox hoặc bất kỳ điều khiển nào khác mà bạn đặt sự kiện.

Một điều thú vị về điều này là bạn có thể sử dụng cùng một sự kiện cho tất cả các loại điều khiển vì chúng đều lấy được từ phần tử Khung. Ngoài ra, thiết lập IsSelected (thay vì thiết lập SelectedItem) sẽ khiến nhiều mục được chọn khi bạn đặt SelectionMode của hộp danh sách thành "Extended", có thể hoặc không thể là thứ bạn đang tìm kiếm.

ví dụ:

C# mã

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

Chúng tôi sử dụng các phong cách sau đây để thiết lập một PreviewGotKeyboardFocus mà xử lý tất cả các sự kiện của điều khiển TextBox và ComboBoxes và như vậy:

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

Và sau đó chúng tôi chọn hàng trong mã sau:

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

này chắc chắn dường như phương pháp tốt nhất. Tôi có một hệ thống phân cấp lồng nhau sâu sắc, ListBoxes chứa trong ListBoxes khác, và các điều khiển khác nhau chứa bên trong. Phương pháp này chỉ hoạt động, bởi vì nó chỉ sử dụng ListBoxItem và không phải là điều khiển chứa. Một thay đổi được đề xuất mặc dù - đơn giản hơn là chỉ cần chọn trực tiếp mục: item.IsSelected = true – Niall

+0

Đề xuất tuyệt vời! Tôi đã thay đổi mã số .. – Arcturus

+2

Grazer có câu trả lời tốt hơn bên dưới – Amsakanna

3

tôi đã sử dụng tương tự như giải pháp của Robert, nhưng không có mã sau (sử dụng hành vi đính kèm).

Để làm như vậy,

Đầu tiên. Tạo lớp riêng biệt 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 
    } 
} 

Thứ hai. Thêm một kiểu trong phần tài nguyên (kiểu của tôi được làm tròn màu đen trên tiêu điểm). Thông báo setter cho tài sản FocusBehaviour.IsListBoxItemSelected. Bạn nên tham khảo nó trong 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> 

'

thứ ba. (tùy chọn, đối với tác vụ ngược lại)

Bạn sẽ gặp, nếu không có bất kỳ nhiệm vụ ngược lại nào tập trung vào TextBox khi ListBoxItem được chọn. Tôi khuyên bạn nên sử dụng một thuộc tính khác của lớp Hành vi, IsFocused. Đây là một mẫu mẫu cho ListBoxItem, xin vui lòng nhận thấy 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> 
3

tôi sử dụng một handler lớp để thiết lập hành vi này. Làm theo cách này sẽ sửa tất cả các dạng xem danh sách trong ứng dụng. Tôi không biết tại sao đây không phải là hành vi mặc định.

Trong App.xaml.cs của bạn, thêm dòng sau vào OnStartup:

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

Hãy chắc chắn để sử dụng TargetType thích hợp: ListViewItem, ListBoxItem hoặc TreeViewItem.

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

Không hoạt động nếu đã tồn tại. – ender

+1

Điều này cũng có vấn đề khiến nó bị loại bỏ khi ListView mất tiêu điểm. Câu trả lời dưới đây tốt hơn từ Arcturus –

0

Hãy thử mã này:

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

tôi không có đủ đại diện cho bình luận, vì vậy tôi gửi bài bình luận của tôi là câu trả lời. Giải pháp của Grazer ở trên không hoạt động trong trường hợp bạn có một điều khiển khác chẳng hạn như Button cần có SelectedItem. Điều này là do theo số Style Trigger, số IsKeyboardFocusWithin trở thành sai khi bạn nhấp vào số Button và số SelectedItem trở thành vô giá trị.

0

Thảo luận cũ, nhưng có lẽ câu trả lời của tôi sẽ giúp người khác ...

Giải pháp của Ben có cùng vấn đề với giải pháp của Grazer. Điều xấu là việc lựa chọn phụ thuộc vào trọng tâm [bàn phím] của hộp văn bản. Nếu bạn có một điều khiển khác trên hộp thoại của mình (tức là một nút) tiêu điểm bị mất khi nhấp vào nút và hộp danh sách trở thành chưa được chọn (SelectedItem == null). Vì vậy, bạn có hành vi khác nhau để nhấp vào mục (bên ngoài hộp văn bản) và nhấp vào hộp văn bản. Điều này là rất tẻ nhạt để xử lý và trông rất lạ.

Tôi khá chắc chắn không có giải pháp XAML thuần túy nào cho việc này. Chúng ta cần viết mã cho điều này. Giải pháp gần với những gì Mark đề xuất.

(trong ví dụ của tôi, tôi sử dụng ListViewItem thay vì ListBoxItem, nhưng giải pháp hoạt động cho cả hai).

Mã-đằng sau:

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

với FindParent (lấy từ 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); 
    } 

Trong DataTemplate của tôi:

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

Sau đây là một việc đơn giản hóa của @ câu trả lời của Ben mà không cần phải ghi đè lên DataTemplate. Nó thậm chí có thể được áp dụng như một kiểu tĩnh. Thử nghiệm với một ListView có chứa một GridView > GridViewColumn > TextBox.

Ví dụ:

<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> 
Các vấn đề liên quan