2011-11-20 9 views
28

Chciałbym rozszerzyć DataGridView, aby dodać drugie ContextMenu, które pozwala wybrać kolumny widoczne w przepuście. Nowe menu kontekstowe będzie wyświetlane po kliknięciu prawym przyciskiem myszy nagłówka kolumny.Jak poprawnie ustawić menu kontekstowe po kliknięciu prawym przyciskiem myszy nagłówka kolumny DataGridView?

Mam trudności z uzyskaniem prawidłowej pozycji poziomej, aby wyświetlić menu kontekstowe. Jak mogę to poprawić?

public partial class Form1 : Form 
{ 
    DataGridView dataGrid; 
    ContextMenuStrip contextMenuStrip;   

    public Form1() 
    { 
     InitializeComponent(); 

     dataGrid = new DataGridView(); 
     Controls.Add(dataGrid); 
     dataGrid.Dock = System.Windows.Forms.DockStyle.Fill; 
     dataGrid.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(ColumnHeaderMouseClick); 
     dataGrid.DataSource = new Dictionary<string, string>().ToList(); 

     contextMenuStrip = new ContextMenuStrip(); 
     contextMenuStrip.Items.Add("foo"); 
     contextMenuStrip.Items.Add("bar"); 
    } 

    private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     if (e.Button == System.Windows.Forms.MouseButtons.Right) 
     { 
      contextMenuStrip.Show(PointToScreen(e.Location)); 
     } 
    } 
} 

Odpowiedz

1

gdzie byłem nie tak było, że DataGridViewCellMouseEventArgs zwraca Lokalizacja/x, y, gdzie mysz kliknięciu ciągu że kolumna nagłówek. Zamiast tego muszę użyć HitTest w zdarzeniu MouseDown siatki, aby uzyskać trafienie w nagłówki kolumn, a następnie zamienić pozycję trafienia z współrzędnych pasów na współrzędne ekranu.

public partial class Form1 : Form 
{ 
    DataGridView dataGrid; 
    ContextMenuStrip contextMenuStrip;   

    public Form1() 
    { 
     InitializeComponent(); 

     dataGrid = new DataGridView(); 
     Controls.Add(dataGrid); 
     dataGrid.Dock = System.Windows.Forms.DockStyle.Fill; 
     //dataGrid.ColumnHeaderMouseClick += ColumnHeaderMouseClick; 
     dataGrid.MouseDown += MouseDown; 
     dataGrid.DataSource = new Dictionary<string, string>().ToList(); 

     contextMenuStrip = new ContextMenuStrip(); 
     contextMenuStrip.Items.Add("foo"); 
     contextMenuStrip.Items.Add("bar"); 
    } 

    private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     if (e.Button == System.Windows.Forms.MouseButtons.Right) 
     { 
      contextMenuStrip.Show(PointToScreen(e.Location)); 
     } 
    } 

    private void MouseDown(object sender, MouseEventArgs e) 
    { 
     if (e.Button == System.Windows.Forms.MouseButtons.Right) 
     { 
      if (dataGrid.HitTest(e.X, e.Y).Type == DataGridViewHitTestType.ColumnHeader) 
      { 
       contextMenuStrip.Show(dataGrid.PointToScreen(e.Location)); 
      } 
     } 
    } 
} 
8

Czy próbowałeś używać Show Overload, który akceptuje kontrolę i pozycję?

Na przykład:

contextMenuStrip.Show(dataGrid, e.Location); 

EDIT: Pełny przykład

public partial class Form1 : Form 
{ 
    DataGridView dataGrid; 
    ContextMenuStrip contextMenuStrip;   

    public Form1() 
    { 
     InitializeComponent(); 

     dataGrid = new DataGridView(); 
     Controls.Add(dataGrid); 
     dataGrid.Dock = System.Windows.Forms.DockStyle.Fill; 
     dataGrid.MouseDown += MouseDown; 
     dataGrid.DataSource = new Dictionary<string, string>().ToList(); 

     contextMenuStrip = new ContextMenuStrip(); 
     contextMenuStrip.Items.Add("foo"); 
     contextMenuStrip.Items.Add("bar"); 
    } 

    private void MouseDown(object sender, MouseEventArgs e) 
    { 
     if (e.Button == System.Windows.Forms.MouseButtons.Right) 
     { 
      if (dataGrid.HitTest(e.X, e.Y).Type == DataGridViewHitTestType.ColumnHeader) 
      { 
       contextMenuStrip.Show(dataGrid, e.Location); 
      } 
     } 
    } 
} 
+0

Menu zawartości pojawia się w lewym górnym rogu ekranu, ponieważ pozycja e.location jest pozycją myszy w nagłówku kolumny. Rozwiązałem teraz problem, ale dziękuję za pomoc. –

+0

Zgodnie z twoją odpowiedzią na twoje pytanie e.lokacja jest w obrębie datagridu, a nie kolumnowego, więc competence_tech było poprawne. –

+0

Wygląda na to, że źle odpowiedziałem na kompetentną odpowiedź i rzeczywiście jest poprawny, jeśli jest używany w ramach zdarzenia MouseDown. –

65

Oto bardzo prosty sposób, aby menu kontekstowe pojawiło się tam, gdzie klikamy je prawym przyciskiem myszy.

obsługi zdarzenia ColumnHeaderMouseClick

private void grid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { 
    if (e.Button == System.Windows.Forms.MouseButtons.Right) { 
    contextMenuHeader.Show(Cursor.Position); 
    } 
} 

contextMenuHeader jest ContextMenuStrip, które można zdefiniować w widoku projektanta lub w czasie pracy.

+3

To powinna być zaakceptowana odpowiedź. – Askolein

+3

+1: Odpowiednią częścią dla mnie był Cursor.Position (teraz czuję się głupio) – NobodysNightmare

+0

Prosty, ale potężny –

13

Aby uzyskać współrzędne kursora myszy, można to zrobić.

ContextMenu.Show(this, myDataGridView.PointToClient(Cursor.Position)); 
+1

To prawda. Przyjęta odpowiedź nie jest kompilowana. – icanbenchurcat

3

e.Location nie wyświetla menu podręczne, w prawidłowych współrzędnych, zamiast po prostu użyć właściwości MousePosition następująco:

ContextMenuStrip.Show(MousePosition) 

lub jawnie

ContextMenuStrip.Show(Control.MousePosition) 
0

Byłaś prawie rację. Po prostu trzeba się do zastosowania metody PointToScreen do kontroli wywołującego:

private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
{ 
    if (e.Button == System.Windows.Forms.MouseButtons.Right) 
    { 
     contextMenuStrip.Show(((DataGridView)sender).PointToScreen(e.Location)); 
    } 
} 

myślę, że to jest najbardziej eleganckie rozwiązanie, ponieważ używa tylko ColumnHeaderMouseClick argumenty i nie Cursor.Position.

2

Pozycja zwrócona jest względem komórki. Musimy więc dodać to przesunięcie.

private void grdView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     if (e.Button == MouseButtons.Right) 
     { 
      var pos = ((DataGridView)sender).GetCellDisplayRectangle(e.ColumnIndex, 
      e.RowIndex, false).Location; 
      pos.X += e.X; 
      pos.Y += e.Y; 
      contextMenuStrip.Show((DataGridView)sender,pos); 
     } 
    } 
Powiązane problemy