2010-02-11 24 views
20

Khi tôi mở rộng các mục trong ảnh treeview để cuộn là cần thiết, một thanh cuộn xuất hiện. Tuy nhiên, nó không di chuyển xuống cho chi nhánh mới được mở rộng - chúng bị cắt bởi phần dưới cùng của điều khiển. Vì vậy, khi tôi tiếp tục mở rộng các mục ở dưới cùng của cây, tôi phải tiếp tục cuộn xuống để xem những đứa trẻ mới theo cách thủ công. Bất cứ ai cũng có một gợi ý về cách làm cho nó tự động cuộn để hiển thị các mục mới được mở rộng?WPF TreeView - Cách cuộn để nhánh mở rộng có thể nhìn thấy

Trả lời

16

Trên TreeView, xử lý sự kiện TreeViewItem.Expanded (bạn có thể làm điều này ở cấp TreeView vì sự kiện bubbling). Trong trình xử lý mở rộng, hãy gọi BringIntoView trên TreeViewItem đã đưa ra sự kiện.

Bạn có thể cần một chút thời gian dùng thử và lỗi để giữ TreeViewItem trong mã trình xử lý sự kiện của bạn. Tôi nghĩ (chưa kiểm tra) rằng đối số người gửi đến trình xử lý sự kiện được mở rộng của bạn sẽ là TreeView (vì đó là nơi mà trình xử lý sự kiện được đính kèm) thay vì TreeViewItem. Và e.Source hoặc e.OriginalSource có thể là một phần tử trong mẫu dữ liệu của TreeViewItem. Vì vậy, bạn có thể cần phải sử dụng VisualTreeHelper để đi lên cây trực quan để tìm TreeViewItem. Nhưng nếu bạn sử dụng trình gỡ rối để kiểm tra người gửi và RoutedEventArgs thì điều này không quan trọng để tìm ra.

(Nếu bạn có thể làm việc này và muốn gói nó lại để bạn không phải đính kèm cùng một trình xử lý sự kiện cho mọi TreeView, bạn nên dễ dàng đóng gói nó như là attached behaviour. . để áp dụng nó khai báo, bao gồm cả thông qua một Style)

+0

Đó thực sự hoạt động hoàn hảo, tôi nghĩ đó sẽ là một vấn đề bởi vì tôi muốn tập trung vào các mục con mở rộng, không phải là mục mà mở rộng, nhưng nó hoạt động một cách chính xác làm thế nào tôi muốn nó. Cảm ơn rất nhiều cho các hành vi kèm theo gợi ý quá, thậm chí tốt hơn. – Jared

+0

Trên thực tế, công trình này cho treeview của tôi, nơi tôi hoàn toàn ghi đè mẫu treeviewitem, nhưng không hoạt động đối với cây treeview đơn giản của tôi, nơi tôi sử dụng mẫu treeviewitem mặc định ... không biết tại sao – Jared

2

Nhờ câu trả lời itowlson của, đây là mở rộng sự kiện mã xử lý mà làm việc cho cả hai cây của tôi

private static void Tree_Expanded(object sender, RoutedEventArgs e) 
{ 
    // ignore checking, assume original source is treeviewitem 
    var treeViewItem = (TreeViewItem)e.OriginalSource; 

    var count = VisualTreeHelper.GetChildrenCount(treeViewItem); 

    for (int i = count - 1; i >= 0; --i) 
    { 
     var childItem = VisualTreeHelper.GetChild(treeViewItem, i); 
     ((FrameworkElement)childItem).BringIntoView(); 
    } 

    // do NOT call BringIntoView on the actual treeviewitem - this negates everything 
    //treeViewItem.BringIntoView(); 
} 
+0

Phần XAML là gì? Tôi đã cố gắng điều chỉnh một số đoạn trích XAML khác từ trang này nhưng nó sẽ không hoạt động vì một lỗi mà tôi không hiểu. – ygoe

+0

Nevermind, tôi đã tìm ra. Bạn cần phải loại bỏ "tĩnh" từ chữ ký phương thức ở trên, sau đó XAML sau hoạt động: ygoe

12

Sử dụng một tài sản phụ thuộc vào một kích hoạt IsSelected:

<Style TargetType="{x:Type TreeViewItem}"> 
<Style.Triggers> 
    <Trigger Property="IsSelected" Value="True"> 
    <Setter Property="commands:TreeViewItemBehavior.BringIntoViewWhenSelected" Value="True" /> 
    </Trigger> 
</Style.Triggers> 

Dưới đây là các mã cho các tài sản phụ thuộc:

public static bool GetBringIntoViewWhenSelected(TreeViewItem treeViewItem) 
{ 
    return (bool)treeViewItem.GetValue(BringIntoViewWhenSelectedProperty); 
} 

public static void SetBringIntoViewWhenSelected(TreeViewItem treeViewItem, bool value) 
{ 
    treeViewItem.SetValue(BringIntoViewWhenSelectedProperty, value); 
} 

public static readonly DependencyProperty BringIntoViewWhenSelectedProperty = 
    DependencyProperty.RegisterAttached("BringIntoViewWhenSelected", typeof(bool), 
    typeof(TreeViewItemBehavior), new UIPropertyMetadata(false, OnBringIntoViewWhenSelectedChanged)); 

static void OnBringIntoViewWhenSelectedChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e) 
{ 
    TreeViewItem item = depObj as TreeViewItem; 
    if (item == null) 
    return; 

    if (e.NewValue is bool == false) 
    return; 

    if ((bool)e.NewValue) 
    item.BringIntoView(); 
} 
+1

Giải pháp này hoạt động ngay cả khi bạn thiết lập lựa chọn từ mã. Các biến thể khác chỉ hoạt động nếu bạn nhấn một nút từ cây. – alexandrudicu

+0

Điều này thật tuyệt vời, hoạt động như một sự quyến rũ! –

+1

Ít nhất phải có tham chiếu đến nguồn gốc: [Giới thiệu về các hành vi được đính kèm trong WPF] (https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF) – bokibeg

13

Bạn có thể sử dụng một EventSetter đơn giản trong phong cách TreeViewItem để gọi phương thức thụ lý sự kiện khi mục được chọn. Sau đó, gọi BringIntoView cho mục.

<TreeView > 
<TreeView.ItemContainerStyle> 
    <Style TargetType="{x:Type TreeViewItem}"> 
    <EventSetter Event="Selected" Handler="TreeViewSelectedItemChanged" /> 
    </Style> 
</TreeView.ItemContainerStyle> 

</TreeView> 

private void TreeViewSelectedItemChanged(object sender, RoutedEventArgs e) 
{ 
    TreeViewItem item = sender as TreeViewItem; 
    if (item != null) 
    { 
     item.BringIntoView(); 
     e.Handled = true; 
    } 
} 
+0

Downvoted này do tai nạn; lấy làm tiếc.Đó là những gì sẽ xảy ra khi một con mèo đi ngang qua bàn phím của bạn. Họ cần một bộ lọc mèo trên SO. :-) –

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