2010-11-16 33 views
10

Tôi có một menu ngữ cảnh mà được các mục menu thông qua liên kết dữ liệu (Tôi đang sử dụng mô hình MVVM):WPF: Ẩn ContextMenu khi trống

<ContextMenu ItemsSource="{Binding Path=ContextMenuItems}" /> 

này hoạt động tốt. Tuy nhiên, trong các trường hợp khi không có mục menu nào để hiển thị, tôi không muốn trình đơn ngữ cảnh hiển thị. Có cách nào để hoàn thành nó không? Một số loại XAML kích hoạt có thể?

Tôi đã thử bắt sự kiện mở đã đóng menu ngữ cảnh khi không có con. Điều này hoạt động nhưng menu ngữ cảnh vẫn nhấp nháy ...

Trả lời

14

Có thể liên kết với các mục trong bộ sưu tập của bạn, và sử dụng công cụ chuyển đổi để đặt chế độ hiển thị của menu ngữ cảnh.

<ContextMenu ItemsSource="{Binding Path=ContextMenuItems}" 
       Visibility="{Binding Path=ContextMenuItems.Count,Converter={StaticResource zeroToHiddenConverter}}"> 

public class ZeroToHiddenConverter:IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     int count = (int) value; 

     if (count == 0) 
     { 
      return Visibility.Hidden; 
     } 
     else 
     { 
      return Visibility.Visible; 
     } 
    } 
+0

Câu trả lời hay! Tôi đã cố gắng để kích hoạt HasItems và thiết lập khả năng hiển thị trên sai nhưng sau đó tôi có một contextmenu nhấp nháy cho một giây thứ hai khi thêm menuitems một lần nữa, nhưng nếu đó không phải là trường hợp ở đây thì đây chắc chắn là cách để làm điều đó. –

+0

Rất vui khi biết điều đó. Vui lòng đánh dấu mục này là đã trả lời nếu không có gì khác cần được thêm vào. – ThomasAndersson

+0

Hoạt động tốt! Cảm ơn bạn Tendlon! :) – haagel

0

Bạn có thể thử làm một ràng buộc đối với Tầm nhìn trên Items.Count với bộ chuyển đổi giá trị - mà nên ngăn chặn đơn của bạn xuất hiện :)

0

Nếu bạn sử dụng giải pháp Tendlon về một Kiểm soát TreeView (và có thể là bất kỳ điều khiển kiểu danh sách nào) với một menu ngữ cảnh, nó có vấn đề.

  1. Nhấp chuột phải vào một nút với không Context Menu Items => Không có gì xảy ra (đó là tốt)
  2. nhấp chuột trái vào một nút với Context Menu Items => Các menu ngữ cảnh xuất hiện (mà là xấu)
3

Dưới đây là cách bạn có thể đặt kiểu ứng dụng rộng để ẩn các menu ngữ cảnh trống.

HasItems là thuộc tính phụ thuộc trên chính ContextMenu, vì vậy bạn có thể đặt khả năng hiển thị của menu ngữ cảnh dựa trên boolean đó.

Dưới đây là làm thế nào để làm điều đó trong một cuốn từ điển tài nguyên:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <BooleanToVisibilityConverter x:Key="VisibilityOfBool" /> 

    <Style TargetType="{x:Type ContextMenu}"> 
     <Setter Property="Visibility" Value="{Binding HasItems, RelativeSource={RelativeSource Self}, Converter={StaticResource VisibilityOfBool}}"/> 
    </Style> 
</ResourceDictionary> 
19

Bạn có thể xác định một phong cách tiềm ẩn:

<Style TargetType="{x:Type ContextMenu}"> 
    <Style.Triggers> 
     <Trigger Property="HasItems" Value="False"> 
      <Setter Property="Visibility" Value="Collapsed" /> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

này nên làm việc cho tất cả các menu ngữ cảnh của bạn cùng một lúc.

+2

Làm việc cho tôi. Rất giống với câu trả lời của Adam (upvoted quá), nhưng tôi thích Trigger tốt hơn so với BooleanToVisibilityConverter. Và rõ ràng là tốt hơn câu trả lời được chấp nhận - Tôi chưa trải nghiệm menu ngữ cảnh nhấp nháy mà Meleak đã đề cập. –

+1

Tốt hơn tùy chọn Chuyển đổi. Vấn đề còn lại là thuộc tính HasItems cũng đúng khi các Item (MenuItems) là vô hình. Không có tài sản HasVisibleItems: - / – mamuesstack

0

Tôi đã đưa ra giải pháp cho TreeView sử dụng gọi lại OnContextMenuOpening. Nó ngăn chặn vấn đề Alex G đã đề cập. Nếu bạn thu gọn menu với kiểu XAML thì nó sẽ không xuất hiện khi contextmenu rỗng, tuy nhiên nó xuất hiện sau đó khi bạn nhấp chuột trái vào một mục khác.

Mã tìm kiếm TreeViewItem muốn mở ContextMenu và nếu nó không có mục, nó sẽ đặt thuộc tính Handled của sự kiện thành true.

protected override void OnContextMenuOpening(ContextMenuEventArgs e) { 
    var item = FindTreeViewItem(e.OriginalSource as DependencyObject); 
    var contextMenu = item.ContextMenu; 
    if (contextMenu != null && !contextMenu.HasItems) { 
     e.Handled = true; 
    } 
} 

private TreeViewItem FindTreeViewItem(DependencyObject dependencyObject) { 
    if (dependencyObject == null) { 
     return null; 
    } 
    var treeViewItem = dependencyObject as TreeViewItem; 
    if (treeViewItem != null) { 
     return treeViewItem; 
    } 
    return FindTreeViewItem(VisualTreeHelper.GetParent(dependencyObject)); 
} 
Các vấn đề liên quan