2009-07-25 37 views
5

Tôi có Expander trong ItemTemplate của ListBox. Người cho vay tốt. Vấn đề tôi gặp phải là tôi muốn sự kiện ListBox_SelectionChanged kích hoạt khi bộ mở rộng được mở rộng và/hoặc được chọn. Sự kiện MouseDown dường như không bong bóng lên ListBox.WPF Listbox + Expander events

Điều tôi cần là SelectedIndex của ListBox. Bởi vì ListBox_SelectionChanged không bị sa thải, chỉ mục là -1 và tôi không thể xác định mục nào đã được chọn.

Sự kiện ListBox_SelectionChanged được kích hoạt nếu người dùng nhấp vào Nội dung của Expander sau khi nó đã được mở rộng. Nếu họ chỉ bấm vào expander, sự kiện này không được kích hoạt. Điều này gây nhầm lẫn cho người dùng bởi vì trực quan, họ nghĩ rằng họ đã nhấp vào mục đó khi thực sự nhấp vào Tiêu đề Expander. Tôi cần mục ListBox được chọn khi người dùng mở rộng Expander bởi vì theo như người dùng quan tâm, mục này hiện được chọn khi nó thực sự không.

Bất kỳ đề xuất nào về cách làm việc này hoặc cách thay thế để xác định SelectedIndex của hộp danh sách có bộ mở rộng trong đó?

đang Giản để tham khảo:

<Window x:Class="WpfApplication3.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300" 
    Loaded="Window_Loaded"> 
    <Grid Name="Root"> 
     <ScrollViewer> 
      <ListBox SelectionChanged="ListBox_SelectionChanged" ItemsSource="{Binding}"> 
       <ItemsControl.ItemTemplate > 
        <DataTemplate> 
         <Border> 
          <Expander> 
           <Expander.Header> 
            <TextBlock Text="{Binding Path=Name}"/> 
           </Expander.Header> 
           <Expander.Content> 
            <StackPanel> 
             <TextBlock Text="{Binding Path=Age}"/> 
             <TextBlock Text="Line 2"/> 
             <TextBlock Text="Line 3"/> 
            </StackPanel> 
           </Expander.Content> 
          </Expander> 
         </Border> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ListBox> 
     </ScrollViewer> 
    </Grid> 
</Window> 

Simple lớp cho Binding:

public class Person 
{ 
    public string Name { 
     get; 
     set; 
    } 

    public int Age { 
     get; 
     set; 
    } 
} 

Tạo và Populating dữ liệu cho ràng buộc:

private void Window_Loaded(object sender, RoutedEventArgs e) { 

    data = new ObservableCollection<Person>(); 

    data.Add(new Person { 
     Name = "One", 
     Age=10 
    }); 

    data.Add(new Person { 
     Name = "Two", 
     Age = 20 
    }); 

    data.Add(new Person { 
     Name = "Three", 
     Age = 30 
    }); 

    Root.DataContext = data; 
} 

Đây là sự kiện tôi cần (thực sự chỉ là SelectedIndex tôi cần)

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { 
    ListBox box = (ListBox)sender; 

    // This value is not set because events from Expander are not bubbled up to fire SelectionChanged Event 
    int index = box.SelectedIndex; 
} 

Trả lời

1

Một cách thay thế mà doesnt phụ thuộc vào IsSelected, Bạn có thể treo một mở rộng/Đã thu gọn trường hợp giãn nở vào mã phía sau và sử dụng đoạn mã sau để tìm hiểu chỉ số ListBox mà bạn nhấp vào.

DependencyObject dep = (DependencyObject)e.OriginalSource; 

while ((dep != null) && !(dep is ListViewItem)) 
{ 
    dep = VisualTreeHelper.GetParent(dep); 
} 

if (dep == null) 
    return; 

int index = yourListBox.ItemContainerGenerator.IndexFromContainer(dep); 
4

Điều bạn muốn là để điều khiển Expander kiểm soát lựa chọn ListBox. Bạn có thể dễ dàng lưu trữ điều này bằng cách thiết lập một ràng buộc hai chiều trên tài sản IsExpanded của Expander để ListBoxItem ngay lập tức mà bạn đã bấm.

<Expander IsExpanded="{Binding IsSelected,Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"> 

UPDATE: Nếu bạn cần để tránh sự sụp đổ tự động khi bạn chọn mục khác, hãy lựa chọn chế độ Listbox nhiều.

<ListBox SelectionMode="Multiple" 
+0

Ahh có - điều đó có ý nghĩa và hoạt động! Cảm ơn. – IUnknown

+0

Nó hoạt động ngay bây giờ - nhưng với một tác dụng phụ không mong muốn. Khi tôi mở rộng Expander thứ hai, cái đầu tiên sẽ tự động sụp đổ. Có cách nào để làm điều này mà không tự động thu gọn mục mở rộng trước đó? – IUnknown

+0

Chỉ cần làm cho SelectionMode = "Nhiều" trên ListBox –

0

Cảm ơn Jobi. Đó là khá thông minh. Lỗ thỏ của WPF tiếp tục ngày càng sâu hơn.

Dưới đây là những gì tôi đã dựa trên đề xuất của bạn:

private void Expander_Expanded(object sender, RoutedEventArgs e) { 
    DependencyObject dep = (DependencyObject)sender; 

    while ((dep != null) && !(dep is ListBoxItem)) { 
     dep = VisualTreeHelper.GetParent(dep); 
    } 

    if (dep == null) 
     return; 

    int index = PersonList.ItemContainerGenerator.IndexFromContainer(dep); 

    PersonList.SelectedIndex = index; 
} 

private void Expander_Collapsed(object sender, RoutedEventArgs e) { 
    DependencyObject dep = (DependencyObject)sender; 

    while ((dep != null) && !(dep is ListBoxItem)) { 
     dep = VisualTreeHelper.GetParent(dep); 
    } 

    if (dep == null) 
     return; 

    int index = PersonList.ItemContainerGenerator.IndexFromContainer(dep); 

    if (PersonList.SelectedIndex == index) 
     PersonList.SelectedIndex = -1; 
} 

tôi đã phải thay đổi ListViewItem để ListBoxItem (Tôi đã sử dụng một ListBox).

Ngoài ra, tôi đã sử dụng chỉ mục để chọn hoặc bỏ chọn ListBox.SelectedIndex. Điều này cho tôi trải nghiệm tôi đang tìm kiếm.

  1. Lần đầu tiên người nào đó mở rộng Expander, nó chọn ListBoxItem vừa được mở rộng.

  2. Nếu ai đó mở rộng Expander khác, ListBoxItem trước đó được bỏ chọn, nhưng vẫn được mở rộng, ListBoxItem mới được mở rộng được chọn.

  3. Nếu ai đó thu gọn Expander đã chọn, ListBoxItem sẽ được bỏ chọn.

  4. Nếu có một số Người mở rộng được mở rộng, ai đó thu gọn một bộ mở rộng ListBoxItem không được chọn, thì ListBoxItem đã chọn trước đó vẫn được chọn.

Cảm ơn sự trợ giúp - Tôi nghĩ đây là đoạn mã rất hữu ích cho bất kỳ ai sử dụng Trình tăng tốc trong ListBox.

+0

cool .. Yeah không chỉ expander trong một ListTemplate của Listbox .. Bất kỳ điều khiển như Button/checkbox hoặc bất cứ điều gì bạn thực sự cần loại hack này. –

+0

Tôi nghĩ từ "hack" của bạn phù hợp hơn với công việc "đoạn mã" của tôi. Giải pháp này ở trên không phải là rất đẹp - nó hoạt động - nhưng không đẹp. Nên có một giải pháp thanh lịch hơn sau đó đi bộ đồ thị trực quan. – IUnknown

Các vấn đề liên quan