Avatar billede jm1133 Nybegynder
18. februar 2009 - 10:37 Der er 4 kommentarer

ListView SelectedIndexChanged

Hej,

Jeg har en form med to usercontrols på.
Den ene usercontrol indeholder en listview med en række items som den læser fra en database, og vha en eventhandler på SelectedIndexChanged (samt tilhørende public event for at kunne flytte fra en userform til en anden) bliver detaljer for dette item vist i den anden userform bestående af en række textboxes og selectboxes hvor detaljerne for det enkelte item kan redigeres og gemmes i databasen.
Den del fungerer perfekt!

Så snart man begynder at ændre i en af detaljerne sættes en variabel for at fortælle at detaljerne er ændret men ikke gemt.

Hvis denne variabel er sat og man vælger et nyt item på listen bliver man via en messagebox spurgt om man vil skifte til det nye item uden først at gemme detaljerne for det gamle.

Udfordringen består i at omgå eventhandleren midlertidig således at den bibeholder detaljerne for det tidligere valgte item, og ikke mindst at ændre markeringen i listviewet fra det nyvalgte til det forrige valgte item, vel at mærke uden at eventhandleren reagerer på at man manuelt ændrer det valgte item.

Jeg har forsøgt alverdens ting, og brugt adskillige timer på at forsøge at løse det selv, men nu er jeg løbet tør for idéer.
Avatar billede Knobtemor Nybegynder
24. februar 2009 - 12:08 #1
hej jm1133

Jeg tror jeg forstår hvad du mener, men det er lidt svært uden et kode eksempel. Anyway, jeg prøver at komme med et bud.

Jeg ved god denne løsning er fæl, men uden din kode har jeg ikke bedre ideer...

private int indexValue = -1; //-1 intet valgt.

private void listBox_SelectedIndexChanged(object sender, EventArgs e)
{
  if(indexValue != -1)
  {
      indexValue = listBox.SelectedIndex();
      //do stuff normalt.
  }
  else
  {
      //request user input - keepInfo (boolean)
      if(keepInfo)
      {
          listBox.SelectedIndex(indexValue);
          //gem ændringer, eller hvad der skal ske
      }
      else
      {
          indexValue = listBox.SelectedIndex();
          //ignore ændringer
      }
      //do stuff normalt
  }
}
Avatar billede jm1133 Nybegynder
25. februar 2009 - 10:34 #2
Hej, tak for forslaget. Min egen løsning ligner den meget, men den skaber alligevel problemer da eventhandleren bliver trigget igen når man manuelt ændrer selectedIndex, og man således bliver præsenteret for det samme spørgsmål 4 gange inden det oprindeligt valgte item igen er valgt.

Den oprindelige kode er meget komplex da den kører over flere userforms, men jeg har simplificeret den til én form i nedenstående kode.
Da den oprindelige kode kører med en public eventhandler som også trigger en eventhandler i hovedformen skaber det også andre problemer, men jeg tror at hvis først dette problem bliver løst så vil resten også løse sig. Jeg synes blot det blev alt for indviklet at kopiere kode fra flere forskellige forms og userforms ind her.

Det skulle være lige til at oprette et nyt projekt og copy/paste hele koden ind i Form1.cs
-----------------------------


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("Item1");
            System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("Item2");
            System.Windows.Forms.ListViewItem listViewItem3 = new System.Windows.Forms.ListViewItem("Item3");
            System.Windows.Forms.ListViewItem listViewItem4 = new System.Windows.Forms.ListViewItem("Item4");
            System.Windows.Forms.ListViewItem listViewItem5 = new System.Windows.Forms.ListViewItem("Item5");
            System.Windows.Forms.ListViewItem listViewItem6 = new System.Windows.Forms.ListViewItem("Item6");
            this.listView1 = new System.Windows.Forms.ListView();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.textBox2 = new System.Windows.Forms.TextBox();
            this.button1 = new System.Windows.Forms.Button();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            //
            // listView1
            //
            this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
            listViewItem1,
            listViewItem2,
            listViewItem3,
            listViewItem4,
            listViewItem5,
            listViewItem6});
            this.listView1.Location = new System.Drawing.Point(12, 12);
            this.listView1.MultiSelect = false;
            this.listView1.Name = "listView1";
            this.listView1.Size = new System.Drawing.Size(404, 170);
            this.listView1.TabIndex = 0;
            this.listView1.UseCompatibleStateImageBehavior = false;
            this.listView1.View = System.Windows.Forms.View.List;
            this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged);
            //
            // textBox1
            //
            this.textBox1.Location = new System.Drawing.Point(184, 217);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(232, 20);
            this.textBox1.TabIndex = 1;
            this.textBox1.TextChanged += new System.EventHandler(this.textBox_TextChanged);
            //
            // textBox2
            //
            this.textBox2.Location = new System.Drawing.Point(184, 243);
            this.textBox2.Name = "textBox2";
            this.textBox2.Size = new System.Drawing.Size(232, 20);
            this.textBox2.TabIndex = 2;
            this.textBox2.TextChanged += new System.EventHandler(this.textBox_TextChanged);
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(341, 269);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 3;
            this.button1.Text = "Gem";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.buttonSave_Click);
            //
            // label1
            //
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(181, 201);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(60, 13);
            this.label1.TabIndex = 4;
            this.label1.Text = "(Intet valgt)";
            //
            // label2
            //
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(9, 282);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(35, 13);
            this.label2.TabIndex = 5;
            this.label2.Text = "-1";
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(428, 304);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.textBox2);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.listView1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.ListView listView1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.TextBox textBox2;
        private System.Windows.Forms.Button button1;

        private bool ChangedButNotSaved = false;
        private int SelectedItem = -1;

        private void textBox_TextChanged(object sender, EventArgs e)
        {
            //Rød tekst på gem knappen indikerer at der er foretaget ændringer i en af TextBoxene.
            button1.ForeColor = Color.Red;
            ChangedButNotSaved = true;
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            //I dette eksempel gemmes ingenting, men tekstfarven på Gem knappen bringes tilbage til den oprindelige sorte.
            button1.ForeColor = Color.Black;
            ChangedButNotSaved = false;
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listView1.SelectedIndices.Count > 0)
            {
                if (ChangedButNotSaved == false)
                {
                    // Her skifter vi indhold som normalt, ingen problemer her:
                    label1.Text = listView1.Items[listView1.SelectedIndices[0]].Text;
                    textBox1.Enabled = true;
                    textBox1.Text = "";
                    textBox2.Enabled = true;
                    textBox2.Text = "";
                    SelectedItem = listView1.SelectedIndices[0];
                    label2.Text = SelectedItem.ToString();
                }
                else
                {
                    //Hvis teksten er ændret men ikke gemt bliver vi spurgt om vi vil skifte til det nye valg og dermed miste alle ændringer:
                    DialogResult answer = MessageBox.Show("Denne handling vil nulstille alle ændringer til det åbne item.\n\nØnsker du at lukke det åbne item uden at gemme ændringerne?", "Advarsel!", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                    if (answer == DialogResult.Yes)
                    {
                        //Ja det vil vi gerne, så vi skifter indhold som normalt samt nulstiller ChangedButNotSaved
                            label1.Text = listView1.Items[listView1.SelectedIndices[0]].Text;
                            SelectedItem = listView1.SelectedIndices[0];
                            label2.Text = SelectedItem.ToString();
                            textBox1.Enabled = true;
                            textBox1.Text = "";
                            textBox2.Enabled = true;
                            textBox2.Text = "";
                            button1.ForeColor = Color.Black;
                            ChangedButNotSaved = false;
                    }
                    else
                    {
                        //Hvis vi vælger ikke at skifte item på listen vælger vi her det item som var valgt inden brugeren valgte et nyt, og vi bibeholder således dataene i TextBoxene.
                        //Problemet består i at når vi ændrer det valgte item tilbage, vil denne eventhandler blive trigget igen.
                        listView1.Items[SelectedItem].Selected = true;
                    }
                }
            }
            else
            {
          //    SelectedItem = -1;
                label2.Text = SelectedItem.ToString();
            }
        }
    }

}
Avatar billede Knobtemor Nybegynder
26. februar 2009 - 16:45 #3
Hej jm1133

Okay, jeg forstod dig rigtigt.

Den eneste åbenlyse metode jeg kan komme på, uden at vi skal til at lave en custom event der kigger på det tidligere valgte index, er simplethen at "skippe" alt contant i eventet, såfremt tidligere valgte index er lig med det index som bliver valgt.

(jeg viser eksemplet i min kode da denne er nemmere at overskue her på siden )

private int indexValue = -1; //-1 intet valgt.

private void listBox_SelectedIndexChanged(object sender, EventArgs e)
{
  //Denne if sætning checker om det nye index er lig det tidligere valgte.
  if(indexvalue != listBox.SelectedIndex())
  {
    if(indexValue != -1)
    {
        indexValue = listBox.SelectedIndex();
        //do stuff normalt.
    }
    else
    {
        //request user input - keepInfo (boolean)
        if(keepInfo)
        {
            listBox.SelectedIndex(indexValue);
            //gem ændringer, eller hvad der skal ske
        }
        else
        {
            indexValue = listBox.SelectedIndex();
            //ignore ændringer
        }
        //do stuff normalt
    }
  }
}
Avatar billede jm1133 Nybegynder
26. februar 2009 - 23:50 #4
Hej Knobtemor,

Ja du har helt afgjort fanget den rigtige problemstilling, og jeg har selv i den oprindelige kode leget med mange varianter af at tjekke om tidligere index = valgte index, men det er aldrig lykkedes at få det til at fungere 100%.
Jeg ved ikke om forskellen ligger i at jeg i min kode anvender et listview og du i din kode en listbox, men hvis jeg har redigeret indholdet i en af textboxene, og vælger et nyt item bliver jeg præsenteret for dialogboxen to gange hvor jeg begge gange skal svare nej for at blive på det valgte item.

Prøv den kode jeg gav herinde i går, og erstat eventhandleren med følgende kode som netop tjekker om valgte index = forrige index. Jeg har lagt lidt messageboxes på som udskriver værdien af relevante variable, men kan stadig ikke gennemskue hvorfor spørgsmålet kommer to gange.

--------------------------------------

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            MessageBox.Show("listView1.SelectedIndices.Count = " + listView1.SelectedIndices.Count.ToString());
            if (listView1.SelectedIndices.Count > 0)
            {
                MessageBox.Show("listView1.SelectedIndices[0] = " + listView1.SelectedIndices[0].ToString() + "\n" +
                    "SelectedItem = " + SelectedItem.ToString());
                if (listView1.SelectedIndices[0] != SelectedItem)
                {
                    MessageBox.Show("ChangedButNotSaved = " + ChangedButNotSaved.ToString());
                    if (ChangedButNotSaved == false)
                    {
                        // Her skifter vi indhold som normalt, ingen problemer her:
                        label1.Text = listView1.Items[listView1.SelectedIndices[0]].Text;
                        textBox1.Enabled = true;
                        textBox1.Text = "";
                        textBox2.Enabled = true;
                        textBox2.Text = "";
                        SelectedItem = listView1.SelectedIndices[0];
                        label2.Text = SelectedItem.ToString();
                    }
                    else
                    {
                        //Hvis teksten er ændret men ikke gemt bliver vi spurgt om vi vil skifte til det nye valg og dermed miste alle ændringer:
                        DialogResult answer = MessageBox.Show("Denne handling vil nulstille alle ændringer til det åbne item.\n\nØnsker du at lukke det åbne item uden at gemme ændringerne?", "Advarsel!", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                        if (answer == DialogResult.Yes)
                        {
                            //Ja det vil vi gerne, så vi skifter indhold som normalt samt nulstiller ChangedButNotSaved
                            label1.Text = listView1.Items[listView1.SelectedIndices[0]].Text;
                            SelectedItem = listView1.SelectedIndices[0];
                            label2.Text = SelectedItem.ToString();
                            textBox1.Enabled = true;
                            textBox1.Text = "";
                            textBox2.Enabled = true;
                            textBox2.Text = "";
                            button1.ForeColor = Color.Black;
                            ChangedButNotSaved = false;
                        }
                        else
                        {
                            //Hvis vi vælger ikke at skifte item på listen vælger vi her det item som var valgt inden brugeren valgte et nyt, og vi bibeholder således dataene i TextBoxene.
                            //Problemet består i at når vi ændrer det valgte item tilbage, vil denne eventhandler blive trigget igen.
                            listView1.Items[SelectedItem].Selected = true;
                        }
                    }
                }
            }
            else
            {
                label2.Text = SelectedItem.ToString();
            }
        }
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