2011-01-28 12 views
19

Tôi đang tìm giải pháp trên internet nhưng không thể tìm thấy nó trong mẫu của tôi. Tôi cần phải thêm một dấu phân cách giữa mục trình đơn ngữ cảnh được tạo ra từ mã phía sau. Tôi đã cố gắng để thêm nó với các dòng mã như dưới đây nhưng không thành công.Làm cách nào để thêm dấu phân cách ngang trong ContextMenu được tạo động?

this.Commands.Add(new ToolStripSeparator()); 

Tôi tự hỏi nếu ai đó có thể trợ giúp. Cảm ơn bạn trước.

Context Menu XAML:

<Style x:Key="DataGridCellStyle" TargetType="{x:Type DataGridCell}"> 
    <Setter Property="ContextMenu"> 
     <Setter.Value> 
      <ContextMenu ItemsSource="{Binding Commands}"> 
       <ContextMenu.ItemContainerStyle> 
        <Style TargetType="{x:Type MenuItem}"> 
         <Setter Property="Command" Value="{Binding}" /> 
         <Setter Property="Header" Value="{Binding Path=Text}" /> 
         <Setter Property="CommandParameter" Value="{Binding Path=Parameter}" /> 
        </Style> 
       </ContextMenu.ItemContainerStyle> 
      </ContextMenu> 
     </Setter.Value> 
    </Setter> 

C# mà thêm vào trong phương pháp:

this.Commands = new ObservableCollection<ICommand>(); 
     this.Commands.Add(MainWindow.AddRole1); 
     this.Commands.Add(MainWindow.AddRole2); 
     this.Commands.Add(MainWindow.AddRole3); 
     this.Commands.Add(MainWindow.AddRole4); 
     //this.Add(new ToolStripSeparator()); 
     this.Commands.Add(MainWindow.AddRole5); 
     this.Commands.Add(MainWindow.AddRole6); 
     this.Commands.Add(MainWindow.AddRole7); 

Trả lời

12

Hoặc, thay vì phải ContextMenu ràng buộc của bạn vào một tập hợp các lệnh, ràng buộc nó vào một tập hợp các FrameworkElements sau đó bạn có thể thêm một trong hai MenuItems hoặc phân tách trực tiếp đến việc thu thập và để điều khiển menu làm tất cả những khuôn mẫu. ...

<Style x:Key="DataGridCellStyle" TargetType="{x:Type DataGridCell}"> 
    <Setter Property="ContextMenu"> 
     <Setter.Value> 
      <ContextMenu ItemsSource="{Binding Commands}" /> 
     </Setter.Value> 
    </Setter> 
</Style> 

C#:

this.Commands = new ObservableCollection<FrameworkElement>(); 

this.Commands.Add(new MenuItem {Header = "Menuitem 2", Command = MainWindow.AddRole1}); 
this.Commands.Add(new MenuItem {Header = "Menuitem 2", Command = MainWindow.AddRole2}); 
this.Commands.Add(new MenuItem {Header = "Menuitem 3", Command = MainWindow.AddRole3}); 
this.Commands.Add(new MenuItem {Header = "Menuitem 4", Command = MainWindow.AddRole4}); 

this.Commands.Add(new Separator); 

this.Commands.Add(new MenuItem {Header = "Menuitem 5", Command = MainWindow.AddRole5}); 
this.Commands.Add(new MenuItem {Header = "Menuitem 6", Command = MainWindow.AddRole6}); 
this.Commands.Add(new MenuItem {Header = "Menuitem 7", Command = MainWindow.AddRole7}); 

Chỉ cần sử dụng phương pháp này trong ứng dụng của tôi - tách trông tốt hơn theo cách này cũng có.

+0

Cảm ơn bạn đã chia sẻ kỹ thuật này. – vladc77

+12

Không phải là một ý tưởng tuyệt vời nếu bạn muốn duy trì một mô hình-xem-tách mặc dù. –

+0

Không chắc chắn lý do. Mã này nằm trong ViewModel nên tách biệt với View.True chứa các điều khiển UI có liên quan đến View và nếu bạn muốn giữ chúng khỏi ViewModel, bạn có thể đặt tất cả các chức năng vào một hành vi và liên kết với một danh sách các lệnh cho các mục menu với lệnh giả cho dấu phân cách. – samneric

40

Tôi đã làm điều này một lần và sử dụng một null như tách tôi. Từ XAML, tôi sau đó theo kiểu mẫu để sử dụng thiết bị tách nếu DataContext là vô

Mã đằng sau:

this.Commands.Add(MainWindow.AddRole4); 
this.Add(null); 
this.Commands.Add(MainWindow.AddRole5); 

XAML là một cái gì đó như thế này:

<ContextMenu.ItemContainerStyle> 
    <Style TargetType="{x:Type MenuItem}"> 
     <Setter Property="Command" Value="{Binding}" /> 
     <Setter Property="Header" Value="{Binding Path=Text}" /> 
     <Setter Property="CommandParameter" Value="{Binding Path=Parameter}" /> 

     <Style.Triggers> 
      <DataTrigger Binding="{Binding }" Value="{x:Null}"> 
       <Setter Property="Template" Value="{StaticResource MenuSeparatorTemplate}" /> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</ContextMenu.ItemContainerStyle> 

Hy vọng tôi có cú pháp đúng - Tôi không có IDE trên máy này để xác minh mã

EDIT

Đây là mẫu ví dụ cho trình tách dấu ngữ cảnh. Tôi đặt nó trong ContextMenu.Resources, mặc dù bạn có thể đặt nó ở bất cứ nơi nào bạn muốn trong ứng dụng của bạn miễn là ContextMenu có thể truy cập nó.

<ContextMenu.Resources> 
    <ControlTemplate x:Key="MenuSeparatorTemplate"> 
     <Separator /> 
    </ControlTemplate> 
</ContextMenu.Resources> 
+0

Cảm ơn bạn cho ý tưởng. Tuy nhiên, nó vẫn chưa hoạt động. Tôi chưa thể chèn dấu phân cách. Tôi đã thay đổi giá trị thành 'Value = "{DynamicResource MenuSeparatorTemplate}"' và có thể gỡ lỗi giải pháp. Kết quả là dấu phân cách không hiển thị và vùng đó có trạng thái rollover trên menuitem rỗng. Tôi tự hỏi nếu nó có thể sửa chữa. – vladc77

+0

Bạn cần tạo 'MenuSeparatorTemplate'. Kể từ khi nó không được tạo ra, không có gì đang được hiển thị. – Rachel

+0

Làm cách nào để truy cập mẫu Separator chung từ datatrigger? – vladc77

0

Sử dụng ItemTemplateSelector:

public class MenuItemTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate SeparatorTemplate { get; set; } 

    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     var menuItem = container.GetVisualParent<MenuItem>(); 
     if (menuItem == null) 
     { 
      throw new Exception("Unknown MenuItem type"); 
     } 

     if (menuItem.DataContext == null) 
     { 
      return SeparatorTemplate; 
     } 

     return menuItem.ItemTemplate; 
    } 
} 

XAML:

<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" 

           ItemsSource="{Binding Path=ViewContentMenuItems}" > 
           <ContextMenu.ItemTemplateSelector> 
            <templateSelectors:MenuItemTemplateSelector> 
             <templateSelectors:MenuItemTemplateSelector.SeparatorTemplate> 
              <DataTemplate> 
               <Separator /> 
              </DataTemplate> 
             </templateSelectors:MenuItemTemplateSelector.SeparatorTemplate> 
            </templateSelectors:MenuItemTemplateSelector> 
           </ContextMenu.ItemTemplateSelector> 
          </ContextMenu> 

Trong mô hình:

public ObservableCollection<MenuItem> ViewContentMenuItems 
    { 
     get 
     { 
      var temp = new ObservableCollection<MenuItem>(); 
      temp.Add(null); 
      temp.Add(CreateFolderMenuItem); 
      return temp; 
     } 
    } 
private MenuItem CreateFolderMenuItem 
    { 
     get 
     { 
      var createFolderMenuItem = new MenuItem() 
      { 
       Header = "New Folder", 
       Icon = new Image 
       { 
        Source = new BitmapImage(new Uri("/icons/folderWinCreate.png", UriKind.Relative)), 
        Height = 16, 
        Width = 16 
       } 
      }; 

      Message.SetAttach(createFolderMenuItem, "CreateDocumentsFolder");//Caliburn example 
      return createFolderMenuItem; 
     } 
    } 
+0

Không đặt các yếu tố Xem trong Mô hình Xem, ít nhiều hơn một mô hình. – aaronburro

0

Để làm điều này một cách chính xác cho MVVM bạn phải xác định giao diện mục của riêng bạn (feIMenuItem), tạo các lớp thừa kế cho menu/ContextMenu và cho MenuItem, trong các lớp này ghi đè sau phương pháp bảo vệ ảo:

ItemsControl.PrepareContainerForItemOverride 
ItemsControl.ClearContainerForItemOverride 
ItemsControl.GetContainerForItemOverride 
ItemsControl.IsItemItsOwnContainerOverride 

Đảm bảo rằng phương pháp này tạo cho các mục của loại IMenuItem các thùng chứa mới của bạn có nguồn gốc từ MenuItem loại có ràng buộc tất cả các thuộc tính cần thiết, tại đây bạn có thể phân biệt các loại khác nhau của IMenuItem để hiển thị các mục thông thường, dấu tách hoặc một số loại khác. Đối với các loại không xác định, hãy thực hiện cơ sở cuộc gọi.

Bây giờ, nếu bạn sẽ ràng buộc ItemsSource tài sản của nguồn gốc từ menu/ContextMenu điều khiển mới của bạn với bộ sưu tập của IMenuItem, nó sẽ hiển thị kết quả bạn mong đợi mà không cần đến nay View- thứ trên ViewModel.

2

Tôi đã sửa đổi giải pháp do Rachel cung cấp ở trên để sửa kiểu Kiểu tách. Tôi nhận thấy bài đăng này cũ nhưng vẫn là một trong những kết quả hàng đầu trên Google. Trong tình huống của tôi, tôi đã sử dụng nó cho một Menu so với ContextMenu, nhưng cũng vậy.

XAML

<Menu ItemsSource="{Binding MenuItems}"> 
    <Menu.Resources> 
     <ControlTemplate x:Key="MenuSeparatorTemplate"> 
      <Separator> 
       <Separator.Style> 
        <Style TargetType="{x:Type Separator}" BasedOn="{StaticResource ResourceKey={x:Static MenuItem.SeparatorStyleKey}}"/> 
       </Separator.Style> 
      </Separator> 
     </ControlTemplate> 
     <Style TargetType="{x:Type MenuItem}"> 
      <Setter Property="Header" Value="{Binding MenuItemHeader}" /> 
      <Setter Property="Command" Value="{Binding MenuItemCommand}" /> 
      <Setter Property="CommandParameter" Value="{Binding MenuItemCommandParameter}" /> 
      <Setter Property="ItemsSource" Value="{Binding MenuItemCollection}" /> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding }" Value="{x:Null}"> 
        <Setter Property="Template" Value="{StaticResource MenuSeparatorTemplate}" /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </Menu.Resources> 
</Menu> 

Without Separator Style Change

With Separator Style Change

+1

Chào mừng bạn đến với Stack Overflow! Có vẻ đây là _almost_ một câu trả lời, vì vậy tôi khuyên bạn nên loại bỏ một phần về nó là một bình luận, và thêm nhiều ngữ cảnh để làm cho nó một giải pháp hoàn chỉnh. –