Hi
developing a video application which is almost complete and just getting rid of a few bugs, one i am stuck on is an auto updating list box

i use filesystemwatcher to update contents of listbox and added a bit of code with a textbox to allow me to change the name of listbox item i click on, this works great apart from when i am editing the filename and the listbox updates at same time as this causes the selected index to change so it crashes my application, i guess i need to hold selecteditem value until i finish editing name but i'm at loss at how to do this

I thought about using a lock but not sure if that would stop the listbox updating as well and i was thinking about a using a Variable to store selected index but cant work out how to do this

using vs2008 c#

private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e) 
        { 
 
             
            listBox1.Items.Add(e.FullPath); 
            listBox1.SelectedIndex = listBox1.Items.Count - 1; 
            listBox1.SelectedIndex = -1; 
                    } 
 
        private void listBox1_Click(object sender, EventArgs e) 
        { 
            
            int itemSelected = this.listBox1.SelectedIndex; 
            string itemText = this.listBox1.Items[itemSelected].ToString(); 
 
            Rectangle r = this.listBox1.GetItemRectangle(itemSelected); 
            this.textBox1.Location = new System.Drawing.Point(r.X + 563, r.Y + 569); 
            this.textBox1.Size = new System.Drawing.Size(r.Width + 4, r.Height - 10); 
            this.textBox1.Visible = true; 
            this.textBox1.Text = itemText; 
            this.textBox1.Focus(); 
            this.textBox1.SelectAll(); 
         
        } 
 
        
        private void textBox1_KeyPress(object sender, KeyPressEventArgs e) 
        { 
             
             
            if (e.KeyChar == 13) 
             
            { 
                
                this.listBox1.Items[this.listBox1.SelectedIndex] = this.textBox1.Text; 
                 
                this.textBox1.Visible = false; 
                 
                 
 
            } 
            if (e.KeyChar == 27) 
                this.textBox1.Visible = false;

Recommended Answers

All 6 Replies

All you need is to make

itemSelected

variable global in that class.

Here's a one way to do it. I used a separate textbox for renaming. I suppose you're doing some kind of "inplace" renaming?

// A global variable to hold index of the renamed listbox item
private int _selectedItemIndex;

// I used changed event to trap changes. Of course you have to fill the listbox first
private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
{
    // Check if the name exists -> no duplicates
    if (!listBox1.Items.Contains(e.FullPath))
    {
        listBox1.Items.Add(e.FullPath);
        listBox1.SelectedIndex = listBox1.Items.Count - 1;
    }
    // listBox1.SelectedIndex = -1; ???
}

// private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e) 
// { 
//     listBox1.Items.Add(e.FullPath); 
//     listBox1.SelectedIndex = listBox1.Items.Count - 1; 
//     listBox1.SelectedIndex = -1; 
// } 

private void listBox1_Click(object sender, EventArgs e) 
{ 
    // Use global _selectedItemIndex instead of the procedure local variable
    
    // int itemSelected = this.listBox1.SelectedIndex; 
    _selectedItemIndex = this.listBox1.SelectedIndex; 

    // string itemText = this.listBox1.Items[itemSelected].ToString(); 
    string itemText = this.listBox1.Items[_selectedItemIndex].ToString(); 

    // Rectangle r = this.listBox1.GetItemRectangle(itemSelected); 
    
    // I had to comment this code out and used a separate textbox for renaming
    //Rectangle r = this.listBox1.GetItemRectangle(_selectedItemIndex); 
    //this.textBox1.Location = new System.Drawing.Point(r.X + 563, r.Y + 569); 
    //this.textBox1.Size = new System.Drawing.Size(r.Width + 4, r.Height - 10); 
    this.textBox1.Visible = true; 
    this.textBox1.Text = itemText; 
    this.textBox1.Focus(); 
    this.textBox1.SelectAll(); 
}

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == 13)
    {
        // Check before renaming if the file exists? Can't create a duplicate filename
        if (!File.Exists(this.textBox1.Text))
        {
            string _FileName;

            // Check that filename i.e. this.textBox1.Text is a valid filename!!!
            // no code for that :)

            // Save the current name
            _FileName = this.listBox1.Items[_selectedItemIndex].ToString();
            // Remove item from the list
            this.listBox1.Items.RemoveAt(_selectedItemIndex);
            // Rename the file. Notice: This triggers fileSystemWatcher1_Changed event and the item is added to the listbox again with a new name!
            File.Move(_FileName, this.textBox1.Text);
        }

        // this.listBox1.Items[this.listBox1.SelectedIndex] = this.textBox1.Text;

        _selectedItemIndex = -1; // Nothing is selected
        this.textBox1.Visible = false;
    }
    if (e.KeyChar == 27)
        this.textBox1.Visible = false;
}

You may have to do some modifications to the code, like I had to do in your code. But I hope you'll get the idea how to rename the file and still maintain the listbox's content.

HTH

Thanks for the help
my code ends up as below and works fine, however i now need to add code to check for duplicate filename and a way to stop me selecting and renaming a file that is still being written to.

my project records video to a new file every 60 seconds so if i try and rename a file when its still being written to then my project crashes

private int _selectedItemIndex;

        private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
        {
            listBox1.Items.Add(e.FullPath);
            listBox1.SelectedIndex = listBox1.Items.Count - 1;
            listBox1.SelectedIndex = -1;
        }

        private void listBox1_Click(object sender, EventArgs e)
        {

             _selectedItemIndex = this.listBox1.SelectedIndex; 

            string itemText = this.listBox1.Items[_selectedItemIndex].ToString();

            this.textBox1.Visible = true;
            this.textBox1.Text = itemText;
            this.textBox1.Focus();
            this.textBox1.SelectAll();

        }


        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {


            if (e.KeyChar == 13)
            {
                // Check before renaming if the file exists? Can't create a duplicate filename 
                if (!File.Exists(this.textBox1.Text))  //Doesnt work    
                {            string _FileName;             
                    
                    _FileName = this.listBox1.Items[_selectedItemIndex].ToString(); 
                    // Remove item from the list 
                    this.listBox1.Items.RemoveAt(_selectedItemIndex); 
                    // Rename the file. Notice: This triggers fileSystemWatcher1_Changed event and the item is added to the listbox again with a new name! 
                    File.Move(_FileName, "c:\\Replay\\" + this.textBox1.Text + ".avi");
                }  
                // this.listBox1.Items[this.listBox1.SelectedIndex] = this.textBox1.Text;
                _selectedItemIndex = -1; // Nothing is selected 
                 this.textBox1.Visible = false;


             

              

            } 
            if (e.KeyChar == 27)
                this.textBox1.Visible = false;



        }

There was already check for duplicates:

// Check if the name exists -> no duplicates
if (!listBox1.Items.Contains(e.FullPath))
{
  listBox1.Items.Add(e.FullPath);
  listBox1.SelectedIndex = listBox1.Items.Count - 1;
  listBox1.SelectedIndex = -1;
}

To prevent "crashes" you use try...catch...finally blocks:

// Rename the file
try
{
  File.Move(_FileName, this.textBox1.Text);
  // Remove item from the list (if File.Move() didn't threw an exception)
  this.listBox1.Items.RemoveAt(_selectedItemIndex);
}
catch (Exception)
{
  // Catch the exception (assuming 'file is open' exception)
  // This simply "cancels" renaming
}

Many thanks Guys, 1 day to solve a problem thats been doing my head in for weeks. Good easy to understand replies.

i sorted out duplicate file name it was just a case of pointing to correct directory which i missed due to tiredness.

added the exception and works like a dream. 1 minor thing i would like to fix
i notice i get a beep when i press enter to add new text, is there a way to stop this


My code to help others

private int _selectedItemIndex;

        private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
        {
            listBox1.Items.Add(e.FullPath);
            listBox1.SelectedIndex = listBox1.Items.Count - 1;
            listBox1.SelectedIndex = -1;
        }

        private void listBox1_Click(object sender, EventArgs e)
        {

             _selectedItemIndex = this.listBox1.SelectedIndex; 
// added a catch to stop error when clicking on listbox with no entries in it
  try
            {
                string itemText = this.listBox1.Items[_selectedItemIndex].ToString();
           

            this.textBox1.Visible = true;
            this.textBox1.Text = itemText;
            this.textBox1.Focus();
            this.textBox1.SelectAll();
            }
            catch (ArgumentOutOfRangeException)
            {
            }
        }


        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {


            if (e.KeyChar == 13)
            {
                // Check before renaming if the file exists? Can't create a duplicate filename 
                if (!File.Exists("c:\\Replay\\" +this.textBox1.Text +".avi"))      
                {            string _FileName;            

                    // Save the current name  
                    
                    _FileName = this.listBox1.Items[_selectedItemIndex].ToString(); 
                    // Remove item from the list 

                    try
                    {
                        File.Move(_FileName, "c:\\Replay\\" + this.textBox1.Text + ".avi");
                        this.listBox1.Items.RemoveAt(_selectedItemIndex);
                         
                        
                    }
                    catch (Exception)
                    {
                    }
                }  
                
                _selectedItemIndex = -1; // Nothing is selected 
                 this.textBox1.Visible = false;


              

            } 
            if (e.KeyChar == 27)
                this.textBox1.Visible = false;

i notice i get a beep when i press enter to add new text, is there a way to stop this

That's a system sound coming from an unhandled keypress.

But since you do handle keystrokes in your code, you have to notify system that a keypress is actually handled (no need to beep). Add a one more line of code:

LINE:
58. _selectedItemIndex = -1; // Nothing is selected
59. this.textBox1.Visible = false;
60. e.Handled = true; // <- Tell the system that the keypress has been handled

Once again quick easy to understand replies
problem solved in space of a few days

many thanks for the help on here hopefully i can return the favour to others in future

kenny

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.