2011-03-05 56 views
13

我有一個可能有許多行的數據網格。當用戶右鍵單擊其中一行時,我需要爲每個行顯示一個上下文菜單,並在用戶單擊該選項時執行一個操作(相同的操作,但根據當前選定的行不同的數據項)。爲數據網格行創建上下文菜單

這是最好的策略是什麼?

即使我使用ContextMenuOpening事件創建菜單,對上下文菜單進行「延遲加載」排序,我擔心每個行的ContextMenu都是過度殺傷。我應該只使用一個ContextMenu作爲數據網格嗎?但有了這個我會有更多的工作,關於點擊事件,以確定正確的行,等等。

回答

29

據我所知,一些行動將被禁用或啓用取決於行,所以沒有請撥打ContextMenu以獲得DataGrid

我有一個行級上下文菜單的例子。

​​

DataGrid必須有一個綁定到視圖模型與命令的列表:

public class ItemModel 
{ 
    public ItemModel() 
    { 
     this.EditCommand = new SimpleCommand 
     { 
      ExecuteDelegate = _ => MessageBox.Show("Execute"), 
      CanExecuteDelegate = _ => this.Id == 1 
     }; 
    } 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public ICommand EditCommand { get; set; } 
} 

上下文菜單中UserControl的資源集合創建,我覺得只有一個對象,通過引用與datagrid行連接,而不是按值連接。

這是另一個ContextMenu的示例,其中Command位於MainViewModel之內。我想,DataGrid有一個正確的視圖模型爲DataContext,也CommandParameter屬性必須在命令屬性之前被放置:

<ContextMenu x:Key="RowMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"> 
     <MenuItem Header="Edit" CommandParameter="{Binding}" 
        Command="{Binding DataContext.DataGridActionCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" /> 
    </ContextMenu> 

型號:

public class MainViewModel 
{ 
    public MainViewModel() 
    { 
     this.DataGridActionCommand = new DelegateCommand<ItemModel>(m => MessageBox.Show(m.Title), m => m != null && m.Id != 2); 
    } 

    public DelegateCommand<ItemModel> DataGridActionCommand { get; set; } 
    public List<ItemModel> Items { get; set; } 
} 

public class ItemModel 
{ 
    public int Id { get; set; } 
    public string Title { get; set; } 
} 

但是有一個問題,即MenuItem ISN」如果CanExecute返回false,則顯示爲禁用項目。可能的解決方法是在ItemModel內使用ParentModel屬性,但與第一個解決方案沒有多大差別。 這裏是例如上述解決方案:

public class ItemModel 
{ 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public MainViewModel ParentViewModel { get; set; } 
} 

//Somewhere in the code-behind, create the main view model 
//and force child items to use this model as a parent model 
var mainModel = new MainViewModel { Items = items.Select(item => new ItemViewModel(item, mainModel)).ToList()}; 

而且菜單項中的XAML將simplier:

<MenuItem Header="Edit" CommandParameter="{Binding}" 
       Command="{Binding ParentViewModel.DataGridActionCommand}" /> 
+0

感謝您的樣品,我給它一個嘗試。但是,像你一樣,我也有同樣的疑問,是否只有一個上下文菜單對象?我必須深入研究這一點。 – Jay 2011-03-06 11:32:22

+0

我測試了這個,並且比較了每個行的ContextMenus的哈希代碼,它提供了相同的值,所以它應該是同一個對象。我真的需要每行的命令嗎?我想要像位於主視圖模型內部頂部的父命令一樣使用。這可以通過調整MenuItem中的命令綁定來完成嗎?我無法讓它工作!該死的... – Jay 2011-03-06 13:45:00

+0

@Jay你的意思是一個靜態的RoutedCommand?事實上,可以使用事件處理程序或全局命令而不是行級命令。我會盡量實現類似的明天,如果你可以將你的命令的代碼添加到這個問題,它會幫助我。 – vorrtex 2011-03-06 20:00:30