2016-10-09 122 views
0

當點擊DataGrid中的單元格時,我想不時顯示上下文菜單。 我以編程方式創建ContextMenu,然後使用ContextMenu.IsOpen = true顯示它。在下面的例子中,它在Grid面板內單擊時工作,但它不會單擊DataGrid的單元格(單元內的UIElement)。WPF DataGrid:左鍵單擊時顯示動態上下文菜單

這是區別嗎?我還需要做些什麼來使它在DataGridCell上工作?

這裏有一個演示版本,第一個XAML和下面的代碼。

<Window x:Class="WpfApplication7_delete_me.MainWindow" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:local="clr-namespace:WpfApplication7_delete_me" 
      mc:Ignorable="d" 
      Title="MainWindow" Height="350" Width="525"> 
     <Grid MouseDown="Grid_MouseDown" Background="Beige"> 

     <DataGrid x:Name="dataGrid" HorizontalAlignment="Left" VerticalAlignment="Top" AutoGenerateColumns="False"> 

      <DataGrid.Columns> 
      <DataGridTemplateColumn Header="Name"> 
       <DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Name}" MouseDown="TextBlock_MouseDown" /> 
       </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 
      </DataGridTemplateColumn> 
      </DataGrid.Columns> 

     </DataGrid> 

     </Grid> 
    </Window> 

這裏談到後面的代碼:

using System.Collections.Generic; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Input; 

    namespace WpfApplication7_delete_me { 
     /// <summary> 
     /// Interaction logic for MainWindow.xaml 
     /// </summary> 
     public partial class MainWindow : Window { 
     public MainWindow() { 
      InitializeComponent(); 

      Person p1 = new Person(); p1.Name = "abc"; 
      Person p2 = new Person(); p2.Name = "1q23"; 
      List<Person> l = new List<Person>() { p1, p2 }; 
      dataGrid.ItemsSource = l; 
     } 

     private void Grid_MouseDown(object sender, MouseButtonEventArgs e) { 
      ContextMenu cm = new ContextMenu(); 
      MenuItem mi = new MenuItem(); 
      mi.Header = "hallo"; 
      cm.Items.Add(mi); 
      cm.IsOpen = true; 
     } 

     private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e) { 
      ContextMenu cm = new ContextMenu(); 
      MenuItem mi = new MenuItem(); 
      mi.Header = "hallo"; 
      cm.Items.Add(mi); 
      cm.IsOpen = true; 
     } 
     } 

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

一段時間後,我發現了兩個解決方案:

1)它使用代替的MouseDown PreviewMouseDown在工作。

2)使用:Dispatcher.BeginInvoke(new Action(() => { c.IsOpen = true; }), null);

但是爲什麼設置ISOPEN MouseDown事件中不工作?

+0

你有檢查答案 – AnjumSKhan

+0

我還沒有答案。我剛剛找到了解決方法。問題是,爲什麼MouseDown for DataGrid無法正常工作,而它正在爲例如Grid面板工作。 –

+0

我提到的是顯示動態菜單檢查的標準方法msdn – AnjumSKhan

回答

0

關於第一個解決方案。

使用MouseDown事件時存在一些問題,因爲該事件可能被標記爲由其他控件處理。 PreviewMouseDown是一個預覽事件,並且它不被標記,因此當您使用它時,它將從根元素開始一直向下,並控制到您的實現。

獲取更多信息,您可以在這裏閱讀:MSDN UIElement.MouseDown Event

+0

MouseDown事件不由其他控件處理。設置一個斷點表明,無論何時點擊都會觸發斷點。但是肯定有一些東西阻止了ContextMenu的顯示。 –

0

DataGrid定義一個空ContextMenu

<DataGrid.ContextMenu> 
    <ContextMenu x:Name="CtxMenu">      
    </ContextMenu> 
</DataGrid.ContextMenu> 

和處理ContextMenuOpening事件:

private void DataGrid_ContextMenuOpening_1(object sender, ContextMenuEventArgs e) 
    { 
     ContextMenu ctxmenu = (sender as DataGrid).ContextMenu; 
     // suppress ContextMenu if empty 
     e.Handled = ctxmenu.Items.Count == 0;    
    } 

private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e) 
    { 
     ContextMenu ctxmenu = Dgrd.ContextMenu; 

     MenuItem mi = new MenuItem(); 
     mi.Header = "hallo"; 
     ctxmenu.Items.Add(mi); 
    } 

更好的方式是在DataGrid水平這樣<DataGrid ... DataGridCell.PreviewMouseDown="DataGridCell_MouseDown" ... />處理PreviewMouseDown event

這樣你得到ContextMenuContextMenu ctxmenu = (sender as DataGrid).ContextMenu;。如果你想做一些初步準備,也可以使用預覽事件。

相關問題