Avatar billede r.hegaard Nybegynder
01. marts 2007 - 20:49 Der er 15 kommentarer og
1 løsning

Problemer med sletning af række i DataGridView

Når jeg har en skjult række i et DataGridView og derefter klikker på en række ovenfor, for at slette den, så får jeg en meget mærkelig fejl der siger "InvalidOperationException occurred" og "Current cell cannot be set to an invisible cell."

Jeg har prøvet at søge rundt på nettet, men jeg synes ikke, at jeg kan finde noget, der løser min fejl. Nedenfor har jeg lavet et eksempel, hvor fejlen opstår, hvis man højreklikker på en række og vælger "Hide" og derefter klikker på rækken ovenfor.

Har I nogen forslag til, hvordan problemet kan løses?


using System;
using System.Windows.Forms;
using System.ComponentModel;

namespace Test
{
  public partial class Window : Form
  {
      [STAThread]
      static void Main()
      {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault( false );
        Application.Run( new Window() );
      }

      public Window()
      {
        InitializeComponent();
        grid.Columns.Add( "1", "1" );
        grid.Columns.Add( "2", "2" );
        DataGridViewRow row1 = new DataGridViewRow();
        DataGridViewRow row2 = new DataGridViewRow();
        DataGridViewRow row3 = new DataGridViewRow();
        row1.ContextMenuStrip = contextMenuStrip1;
        row2.ContextMenuStrip = contextMenuStrip1;
        row3.ContextMenuStrip = contextMenuStrip1;
        grid.Rows.Add( row1 );
        grid.Rows.Add( row2 );
        grid.Rows.Add( row3 );
      }

      private void grid_CellMouseDown( object sender, DataGridViewCellMouseEventArgs e )
      {
        if (e.RowIndex > -1 && e.RowIndex < grid.Rows.Count)
        {
            lastRow = grid.Rows[e.RowIndex];
            if (e.Button == MouseButtons.Left) grid.Rows.Remove( lastRow );
        }else lastRow = null;
      }

      private void hideToolStripMenuItem_Click( object sender, EventArgs e )
      {
        if (lastRow != null) lastRow.Visible = false;
      }

      private void InitializeComponent()
      {
        this.grid = new System.Windows.Forms.DataGridView();
        this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip();
        this.hideToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
        ((System.ComponentModel.ISupportInitialize)(this.grid)).BeginInit();
        this.contextMenuStrip1.SuspendLayout();
        this.SuspendLayout();
        this.grid.AllowUserToAddRows = false;
        this.grid.AllowUserToDeleteRows = false;
        this.grid.ReadOnly = true;
        this.grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
        this.grid.Name = "grid";
        this.grid.Dock = DockStyle.Fill;
        this.grid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
        this.grid.CellMouseDown += new System.Windows.Forms.DataGridViewCellMouseEventHandler( this.grid_CellMouseDown );
        this.contextMenuStrip1.Items.AddRange( new System.Windows.Forms.ToolStripItem[] {this.hideToolStripMenuItem} );
        this.contextMenuStrip1.Name = "contextMenuStrip1";
        this.contextMenuStrip1.Size = new System.Drawing.Size( 153, 48 );
        this.hideToolStripMenuItem.Name = "hideToolStripMenuItem";
        this.hideToolStripMenuItem.Size = new System.Drawing.Size( 152, 22 );
        this.hideToolStripMenuItem.Text = "Hide";
        this.hideToolStripMenuItem.Click += new System.EventHandler( this.hideToolStripMenuItem_Click );
        this.Controls.Add( this.grid );
        this.Name = "Window";
        this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
        ((System.ComponentModel.ISupportInitialize)(this.grid)).EndInit();
        this.contextMenuStrip1.ResumeLayout( false );
        this.ResumeLayout( false );
      }

      private ContextMenuStrip contextMenuStrip1;
      private ToolStripMenuItem hideToolStripMenuItem;
      private DataGridView grid;     
      private DataGridViewRow lastRow = null;
  }
}
Avatar billede bulgroz Nybegynder
01. marts 2007 - 22:50 #1
Prøv at beskriv hvad du gerne vil opnå.

Jeg har bikset nedenstående metode sammen som viser hvorledes du kan skjule sidste visible række:

Men bemærk at det kun er et hurtigt eksempel, som blot skjuler sidste række, men du kan naturligvis også slette.

Du kan f.eks. kalde metoden fra din hideToolStripMenuItem metode!


private void HideLastRow()
      {
          DataGridViewRow currentRow = this.grid.CurrentRow;
          int lastRowIndex = this.grid.Rows.GetLastRow(DataGridViewElementStates.Visible);

          if (currentRow != null && currentRow.Index == lastRowIndex)
          {
              int previousRowIndex = this.grid.Rows.GetPreviousRow(currentRow.Index, DataGridViewElementStates.Visible);

              DataGridViewRow previousRow = this.grid.Rows[previousRowIndex];

              if (previousRow != null)
              {
                  currentRow.Visible = false;
                  previousRow.Selected = true;
              }
          }
      }

Nb... Et lille hint til demodata...
       
        // Demodata...
        this.grid.RowCount = 5;
        this.grid.ColumnCount = 3;

        foreach (DataGridViewRow row in this.grid.Rows)
        {
            row.ContextMenuStrip = contextMenuStrip1;
           
            foreach (DataGridViewColumn column in this.grid.Columns)
            {
                row.Cells[column.Index].Value = row.Index;
            }
        }
Avatar billede bulgroz Nybegynder
01. marts 2007 - 22:52 #2
Med andre ord, så har DataGridView.Rows en masse metoder du kan anvende til at finde den row du ønsker (Previous, Next osv...) og med flags til at markere hvilken state rækken skal have for at den er attraktiv for dit udvalg.
Avatar billede r.hegaard Nybegynder
01. marts 2007 - 23:04 #3
bulgroz> Tak for svaret.
Jeg forstår ikke helt dit svar.
Jeg har ikke brug for at finde nogle rækker, jeg vil bare gerne vide, hvordan jeg undgår den fejl, som jeg har beskrevet. Kan du genskabe den?

Jeg har et program, hvor jeg i nogle tilfælde har brug for at skjule nogle rækker og i nogle andre tilfælde at slette nogle rækker ved at klikke på dem. I den forbindelse har jeg fået ovenstående problem, som jeg ikke umiddelbart kan løse.
Avatar billede bulgroz Nybegynder
01. marts 2007 - 23:56 #4
Kort fortalt så er din algoritme for at sætte last row forkert.
Jeg har brygget et mere udvidet eksempel til dig som viser hvorledes du bør håndtere Mouse Down samt din Menu.

I mit eksempel lader jeg Mouse Down sætte focus på rækken. Men det er kun et eksempel. Normalt vil man binde den celle som får focus i en variabel som du kan spørge på når du eksekverer din menu, så man kan styre indholdet i menuen.

I nedenstående eksempel lader jeg kun menuen dukke op hvis den forsøges eksekveret på sidste række.

Eksemplet skjuler rækker, og det kan naturligvis udvides til at vise dem igen.

Jeg håbet at nedenstående er nemmere at forstå.


using System;
using System.Windows.Forms;
using System.ComponentModel;

namespace Test
{
  public partial class Window : Form
  {
      [STAThread]
      static void Main()
      {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault( false );
        Application.Run( new Window() );
      }

      public Window()
      {
        InitializeComponent();

        // Demodata...
        this.grid.RowCount = 5;
        this.grid.ColumnCount = 3;

        foreach (DataGridViewRow row in this.grid.Rows)
        {
            row.ContextMenuStrip = contextMenuStrip1;
           
            foreach (DataGridViewColumn column in this.grid.Columns)
            {
                row.Cells[column.Index].Value = row.Index;
            }
        }
      }

      private void HideLastRow()
      {
          DataGridViewRow currentRow = this.grid.CurrentRow;
          int lastRowIndex = this.grid.Rows.GetLastRow(DataGridViewElementStates.Visible);

          if (currentRow != null && currentRow.Index == lastRowIndex)
          {
              int previousRowIndex = this.grid.Rows.GetPreviousRow(currentRow.Index, DataGridViewElementStates.Visible);

              DataGridViewRow previousRow = null;

              if (previousRowIndex >= 0)
              {
                previousRow = this.grid.Rows[previousRowIndex];
                previousRow.Selected = true;
              }

              currentRow.Visible = false;
          }
      }

      private void hideToolStripMenuItem_Click( object sender, EventArgs e )
      {
          this.HideLastRow();
      }

      private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
      {
          // Dette eksempel viser kun Menuen hvis current row er last visible row.
          DataGridViewRow currentRow = this.grid.CurrentRow;
          int lastRowIndex = this.grid.Rows.GetLastRow(DataGridViewElementStates.Visible);

          if (currentRow == null || currentRow.Index != lastRowIndex)
          {
              e.Cancel = true;
          }
      }

      private void grid_MouseDown(object sender, MouseEventArgs e)
      {
          // Dette eksempel skifter current cell ved højreklik, og derved også current row grundet "FullRowSelect".
          // Overvej at gemme celleværdien til brug for menuafvikling etc.
          if (e.Button == MouseButtons.Right)
          {
              DataGridView.HitTestInfo hitTestInfo = this.grid.HitTest(e.X, e.Y);
              if (hitTestInfo.Type == DataGridViewHitTestType.Cell)
              {
                  DataGridViewCell clickedCell = this.grid.Rows[hitTestInfo.RowIndex].Cells[hitTestInfo.ColumnIndex];

                  if (clickedCell != null)
                  {
                      this.grid.CurrentCell = clickedCell;
                  }
              }
          }
      }

      private void InitializeComponent()
      {
          this.components = new System.ComponentModel.Container();
          this.grid = new System.Windows.Forms.DataGridView();
          this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
          this.hideToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
          ((System.ComponentModel.ISupportInitialize)(this.grid)).BeginInit();
          this.contextMenuStrip1.SuspendLayout();
          this.SuspendLayout();
          //
          // grid
          //
          this.grid.AllowUserToAddRows = false;
          this.grid.AllowUserToDeleteRows = false;
          this.grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
          this.grid.Dock = System.Windows.Forms.DockStyle.Fill;
          this.grid.Location = new System.Drawing.Point(0, 0);
          this.grid.MultiSelect = false;
          this.grid.Name = "grid";
          this.grid.ReadOnly = true;
          this.grid.RowTemplate.Height = 24;
          this.grid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
          this.grid.Size = new System.Drawing.Size(292, 260);
          this.grid.TabIndex = 1;
          this.grid.MouseDown += new System.Windows.Forms.MouseEventHandler(this.grid_MouseDown);
          //
          // contextMenuStrip1
          //
          this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.hideToolStripMenuItem});
          this.contextMenuStrip1.Name = "contextMenuStrip1";
          this.contextMenuStrip1.Size = new System.Drawing.Size(120, 26);
          this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening);
          //
          // hideToolStripMenuItem
          //
          this.hideToolStripMenuItem.Name = "hideToolStripMenuItem";
          this.hideToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
          this.hideToolStripMenuItem.Text = "Hide";
          this.hideToolStripMenuItem.Click += new System.EventHandler(this.hideToolStripMenuItem_Click);
          //
          // Window
          //
          this.ClientSize = new System.Drawing.Size(292, 260);
          this.Controls.Add(this.grid);
          this.Name = "Window";
          this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
          ((System.ComponentModel.ISupportInitialize)(this.grid)).EndInit();
          this.contextMenuStrip1.ResumeLayout(false);
          this.ResumeLayout(false);

      }

      private ContextMenuStrip contextMenuStrip1;
      private ToolStripMenuItem hideToolStripMenuItem;
      private DataGridView grid;
      private IContainer components;     
  }
}
Avatar billede bulgroz Nybegynder
02. marts 2007 - 01:15 #5
Ok, jeg har nok misforstået problemstillingen, sorry. I mine termer er "Last" sidste række ;-)

Det som sker i dit eksempel er at selection handleren i DataGridView automatiskt forsøger at selecte den row du netop har skjult, og man kan ikke selecte en skjult row. At DataGridView ikke tager højde for dette er ikke umiddelbart til at forstå, men uanset hvad, så bør du foretage en sådan operation i en try... catch sætning.

Mit eksempel kan dog sagtens stadig bruges. Du behøver udelukkende at kigge på current row. Og det virker også fint med remove hvis det er det som du ønsker.



      private void HideLastRow()
      {
          DataGridViewRow currentRow = this.grid.CurrentRow;

          if (currentRow != null)
          {
              int previousRowIndex = this.grid.Rows.GetPreviousRow(currentRow.Index, DataGridViewElementStates.Visible);

              if (previousRowIndex >= 0)
              {
                DataGridViewRow previousRow = this.grid.Rows[previousRowIndex];
                previousRow.Selected = true;
              }

              // currentRow.Visible = false;
              this.grid.Rows.Remove(currentRow);
          }
      }

      private void hideToolStripMenuItem_Click( object sender, EventArgs e )
      {
          this.HideLastRow();
      }

      private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
      {
      }

      /// <summary>
      /// Hvis du ønsker at selecte row ved højreklik.
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void grid_MouseDown(object sender, MouseEventArgs e)
      {
          // Dette eksempel skifter current cell ved højreklik, og derved også current row grundet "FullRowSelect".
          // Overvej at gemme celleværdien til brug for menuafvikling etc.
          if (e.Button == MouseButtons.Right)
          {
              DataGridView.HitTestInfo hitTestInfo = this.grid.HitTest(e.X, e.Y);
              if (hitTestInfo.Type == DataGridViewHitTestType.Cell)
              {
                  DataGridViewCell clickedCell = this.grid.Rows[hitTestInfo.RowIndex].Cells[hitTestInfo.ColumnIndex];

                  if (clickedCell != null)
                  {
                      this.grid.CurrentCell = clickedCell;
                  }
              }
          }
      }
Avatar billede r.hegaard Nybegynder
02. marts 2007 - 08:34 #6
bulgroz> Tak for svaret.

I dit eksempel kan man ikke klikke på rækken for at slette den og højreklikke for at skjule den. Det er det jeg har brug for.

Men jeg har prøvet at overføre din kode med PreviousRow til mit eksempel, men det ser ikke ud til, at det virker.
Avatar billede bulgroz Nybegynder
02. marts 2007 - 08:49 #7
Som sagt det var kun et eksempel, sådan havde jeg lavet det bevidst, da jeg personligt syntes at det virker mærkeligt at slette noget uden varsel blot ved klik.


Men øjeblik, jeg retter lige eksemplet.
Avatar billede bulgroz Nybegynder
02. marts 2007 - 09:10 #8
Her en ny udgave som kan det du søger:

using System;
using System.Windows.Forms;
using System.ComponentModel;

namespace Test
{
    public partial class Window : Form
    {
        DataGridViewCell clickedCell;

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Window());
        }

        public Window()
        {
            InitializeComponent();

            // Demodata...
            this.grid.RowCount = 5;
            this.grid.ColumnCount = 3;

            foreach (DataGridViewRow row in this.grid.Rows)
            {
                row.ContextMenuStrip = contextMenuStrip1;

                foreach (DataGridViewColumn column in this.grid.Columns)
                {
                    row.Cells[column.Index].Value = row.Index;
                }
            }
        }

        private void HideLastRow()
        {
            DataGridViewRow currentRow = this.grid.CurrentRow;

            if (currentRow != null)
            {
                int previousRowIndex = this.grid.Rows.GetPreviousRow(currentRow.Index, DataGridViewElementStates.Visible);

                if (previousRowIndex >= 0)
                {
                    DataGridViewRow previousRow = this.grid.Rows[previousRowIndex];
                    previousRow.Selected = true;
                }

                currentRow.Visible = false;
            }
        }

        private void hideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.HideLastRow();
        }

        /// <summary>
        /// Hvis du ønsker at selecte row ved højreklik.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void grid_MouseDown(object sender, MouseEventArgs e)
        {
            // Dette eksempel skifter current cell ved højreklik, og derved også current row grundet "FullRowSelect".
            // Overvej at gemme celleværdien til brug for menuafvikling etc.
            DataGridView.HitTestInfo hitTestInfo = this.grid.HitTest(e.X, e.Y);
            this.clickedCell = (hitTestInfo.Type == DataGridViewHitTestType.Cell) ? this.grid.Rows[hitTestInfo.RowIndex].Cells[hitTestInfo.ColumnIndex] : null;

            switch (e.Button)
            {
                case MouseButtons.Left:
                    if (clickedCell != null)
                    {
                        DataGridViewRow row = this.grid.Rows[this.clickedCell.RowIndex];
                        this.grid.Rows.Remove(row);
                    }
                    break;

                case MouseButtons.Right:
                    if (clickedCell != null)
                    {
                        this.grid.CurrentCell = clickedCell;
                    }
                    break;

                default:
                    break;
            }
        }

        private void buttonShowAll_Click(object sender, EventArgs e)
        {
            foreach (DataGridViewRow row in this.grid.Rows)
            {
                row.Visible = true;
            }
        }

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.grid = new System.Windows.Forms.DataGridView();
            this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.hideToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.buttonShowAll = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.grid)).BeginInit();
            this.contextMenuStrip1.SuspendLayout();
            this.SuspendLayout();
            //
            // grid
            //
            this.grid.AllowUserToAddRows = false;
            this.grid.AllowUserToDeleteRows = false;
            this.grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
            this.grid.Dock = System.Windows.Forms.DockStyle.Top;
            this.grid.Location = new System.Drawing.Point(0, 0);
            this.grid.MultiSelect = false;
            this.grid.Name = "grid";
            this.grid.ReadOnly = true;
            this.grid.RowTemplate.Height = 24;
            this.grid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
            this.grid.Size = new System.Drawing.Size(292, 219);
            this.grid.TabIndex = 1;
            this.grid.MouseDown += new System.Windows.Forms.MouseEventHandler(this.grid_MouseDown);
            //
            // contextMenuStrip1
            //
            this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.hideToolStripMenuItem});
            this.contextMenuStrip1.Name = "contextMenuStrip1";
            this.contextMenuStrip1.Size = new System.Drawing.Size(120, 26);
            //
            // hideToolStripMenuItem
            //
            this.hideToolStripMenuItem.Name = "hideToolStripMenuItem";
            this.hideToolStripMenuItem.Size = new System.Drawing.Size(119, 22);
            this.hideToolStripMenuItem.Text = "Hide";
            this.hideToolStripMenuItem.Click += new System.EventHandler(this.hideToolStripMenuItem_Click);
            //
            // buttonShowAll
            //
            this.buttonShowAll.Location = new System.Drawing.Point(13, 225);
            this.buttonShowAll.Name = "buttonShowAll";
            this.buttonShowAll.Size = new System.Drawing.Size(75, 23);
            this.buttonShowAll.TabIndex = 2;
            this.buttonShowAll.Text = "Show All";
            this.buttonShowAll.UseVisualStyleBackColor = true;
            this.buttonShowAll.Click += new System.EventHandler(this.buttonShowAll_Click);
            //
            // Window
            //
            this.ClientSize = new System.Drawing.Size(292, 260);
            this.Controls.Add(this.buttonShowAll);
            this.Controls.Add(this.grid);
            this.Name = "Window";
            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
            ((System.ComponentModel.ISupportInitialize)(this.grid)).EndInit();
            this.contextMenuStrip1.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        private ContextMenuStrip contextMenuStrip1;
        private ToolStripMenuItem hideToolStripMenuItem;
        private DataGridView grid;
        private Button buttonShowAll;
        private IContainer components;
    }
}
Avatar billede r.hegaard Nybegynder
03. marts 2007 - 12:47 #9
bulgroz> Ja, det ser ud til, at det virker - tak for det.
Så vidt jeg kan se, så er den eneste forskel, at du bruger MouseDown og jeg bruger CellMouseDown. Men hvorfor giver det en forskel?
Avatar billede bulgroz Nybegynder
03. marts 2007 - 15:10 #10
Det er ikke det som er forskellen. Du kan gøre begge dele, din fejl ligger i din anvendelse af "last". Men der er også andre tiltag i din kode som bør revideres.
F.eks. rejses CellKlik eventet kun fra en celle, men alligevel checker du for om det kommer fra en valid row, og på en måde som ikke tager højde for at du arbejder med muligt skjulte rows.
Avatar billede r.hegaard Nybegynder
03. marts 2007 - 16:30 #11
Jeg forstår desværre ikke helt dit svar.
Kan du ikke uddybe lidt, hvad det er der er galt med at bruge "last"?
Og hvad der er galt med den måde jeg tjekker rækker på? En CellMouseDown kan vel ikke give et RowIndex for en skjult række, når man ikke kan klikke på den skjulte række?
Avatar billede bitsch Nybegynder
03. marts 2007 - 19:57 #12
Med hensyn til min kommentar vedr. CellClick.
Det jeg mener er blot at et CellClick event kun kan rejses fra en eksisterende row. Med andre ord så behøver du ikke at checke om rowen eksisterer.
I stedet bør du antage at den kommer fra en row og derefter udføre din remove i en Try... Catch for at fange mulige fejlmuligheder som måtte forekomme med en remove.

Din fejl opstår som sagt fordi DataGridView fejlagtigt forsøget at selecte en row som er hidden (hvilket normalt sker automatiskt efter en remove). Det kommer jeg udenom ved at selecte den row som skal være selectet før jeg remover. Du kan naturligvis tage højde for dette i en try catch, så du kun selecter selv hvis DataGridView ikke selv kan hitte ud af det.

Jeg håber at mit svar er tilstrækkeligt, for jeg er pt. hængt lidt op arbejdsmæssigt så jeg kan ikke garantere at jeg kan nå at uddybe svaret yderligere.
Avatar billede r.hegaard Nybegynder
03. marts 2007 - 21:07 #13
bulgroz == bitsch?

Jeg er ved at være med, men jeg tror ikke, at det vil hjælpe med en Try-Catch. Ved mig bliver fejlen i hvert tilfælde kastet helt ude i main-metoden.

Lægger du et svar, så du kan få dine fortjente point?
Jeg takker mange gange for hjælpen.

Hvis du skulle få tid, så undrer jeg mig stadig over, hvad forskellen er på følgende metoder:

      private void grid_MouseDown( object sender, MouseEventArgs e )
      {
        DataGridView.HitTestInfo hitTestInfo = this.grid.HitTest( e.X, e.Y );
        this.clickedCell = (hitTestInfo.Type == DataGridViewHitTestType.Cell) ? grid[hitTestInfo.ColumnIndex, hitTestInfo.RowIndex] : null;
        switch (e.Button)
        {
            case MouseButtons.Left:
              if (clickedCell != null) this.grid.Rows.Remove( this.grid.Rows[this.clickedCell.RowIndex] );
              break;
            case MouseButtons.Right:
              if (clickedCell != null) this.grid.CurrentCell = clickedCell;
              break;
            default:
              break;
        }
      }     

og

      private void grid_CellMouseDown( object sender, DataGridViewCellMouseEventArgs e )
      {
        if (e.ColumnIndex > -1 && e.RowIndex > -1)this.clickedCell = grid[e.ColumnIndex, e.RowIndex];
        else                                      this.clickedCell = null;
        switch (e.Button){
            case MouseButtons.Left:
              if (clickedCell != null) this.grid.Rows.Remove( this.grid.Rows[this.clickedCell.RowIndex] );
              break;
            case MouseButtons.Right:
              if (clickedCell != null)this.grid.CurrentCell = clickedCell;
              break;
            default:
              break;
        }
      }

Så vidt jeg kan se, så gør de præcist det samme. Den ene bruger bare HitTest til at få RowIndex og den anden får RowIndex fra EventArgs. Hvis man debugger gennem metoderne, så virker det helt fint. Det er altså først efter at CellMouseDown er kaldt, at der sker en fejl.
Avatar billede bulgroz Nybegynder
03. marts 2007 - 21:57 #14
Ups, ja mange navne ;-)... 
Ved din løsning ved du jo allerede at du kan provokere en InvalidOperationException
Som du kan catche, og hvis det skulle hænde kan du så sætte selected row selv inden du sletter rækken.

Hurtigt svar (og sidste)
Jeg gentager.. om du bruger MouseDown eller CellDown er såvidt underordnet, for det er ikke her problemet ligget.
Problemet ligger i dit scenarie hvor du starter med at hide en row og derefter klikker på row'en ovenover. Selection handleren forsøger da automatiskt at selecte en row som er hidden hvilket ikke er tilladt. Hvorfor gridden er lavet sådan står hen i det uvisse.

For at klare dette kan du (bør du) pakke din remove ind i en Try.. Catch... hvis du vælger ikke at sætte selected row selv inden du remover. Se evnt på MSDN, hvor der gennemsås det pattern som du bør anvende følge ved implementering af MouseDown og Context menu (Følg blot F1 hjælpen på dit MouseDown event). Se også på DataGridView.Remove og se hvilke exceptions som kan kastes.

Nb. Du bør altid huske, at hvis du har en formodning om at noget kan ske, så bør du tage højde for det før det sker.
Avatar billede bulgroz Nybegynder
03. marts 2007 - 22:01 #15
Nb2 I øvrigt stemmer det som du er igang med at lave ikke overens med en normal brugeroplevelse i en grid. Du bør overveje om det som du er i færd med at lave nu også er den rette løsning.
Avatar billede r.hegaard Nybegynder
15. marts 2007 - 21:57 #16
bulgroz> Jeg har nu længe arbejdet på dine svar og forsøgt at få det til at virke. Men jeg har ikke umiddelbart fået det til at virke endnu.
Jeg synes, at det virker som om, at du måske har misforstået nogle af mine forklaringer og derfor måske også har givet nogle svar, som er forkerte.
F.eks. skriver du flere gange, at jeg kan catche den exception som kommer. Men når den InvalidOperationException som kommer, bliver kastet helt ude i main-metoden, så hjælper det jo ikke meget, at catche den. Eller kan det gøres på en anden måde?
Du har også flere gange skrevet, at det er lige meget om jeg bruger MouseDown eller CellMouseDown. Men alle dine eksempler, som jeg har testet har jeg ikke kunnet få til at virke, hvis jeg kører det i CellMouseDown. Har du fået det til at virke i CellMouseDown? Kan du give et eksempel, hvor det virker i CellMouseDown?
Grunden til, at jeg gerne vil have det til at virke i CellMouseDown er fordi jeg har en masse anden kode i CellMouseDown, som det her gerne skal hænge sammen med.
Jeg håber, at du har tid til lige at svare på denne her.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester