views:

339

answers:

2

Hi,

Can anyone please explain to my why the form in the code below gets out of focus when selecting a treenode in the tree? What should happen is that the form/button should get the focus when the tree disappears like the listview example but it doesn't.

Code example:

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

namespace FocusTest
{
  public partial class Form1 : Form
  {
    #region Generated

    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    #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.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("Node0");
      System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Node1");
      System.Windows.Forms.TreeNode treeNode3 = new System.Windows.Forms.TreeNode("Node2");
      this.button1 = new System.Windows.Forms.Button();
      this.listView1 = new System.Windows.Forms.ListView();
      this.button2 = new System.Windows.Forms.Button();
      this.treeView1 = new System.Windows.Forms.TreeView();
      this.SuspendLayout();
      // 
      // button1
      // 
      this.button1.Location = new System.Drawing.Point(12, 12);
      this.button1.Name = "button1";
      this.button1.Size = new System.Drawing.Size(75, 23);
      this.button1.TabIndex = 0;
      this.button1.Text = "button1";
      this.button1.UseVisualStyleBackColor = true;
      this.button1.Click += new System.EventHandler(this.button1_Click);
      // 
      // listView1
      // 
      this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
            listViewItem1,
            listViewItem2,
            listViewItem3            
            });
      this.listView1.Location = new System.Drawing.Point(12, 41);
      this.listView1.Name = "listView1";
      this.listView1.Size = new System.Drawing.Size(121, 97);
      this.listView1.TabIndex = 1;
      this.listView1.UseCompatibleStateImageBehavior = false;
      this.listView1.Visible = false;
      this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged);
      this.listView1.View = View.List;
      // 
      // button2
      // 
      this.button2.Location = new System.Drawing.Point(310, 11);
      this.button2.Name = "button2";
      this.button2.Size = new System.Drawing.Size(75, 23);
      this.button2.TabIndex = 2;
      this.button2.Text = "button2";
      this.button2.UseVisualStyleBackColor = true;
      this.button2.Click += new System.EventHandler(this.button2_Click);
      // 
      // treeView1
      // 
      this.treeView1.Location = new System.Drawing.Point(310, 41);
      this.treeView1.Name = "treeView1";
      treeNode1.Name = "Node0";
      treeNode1.Text = "Node0";
      treeNode2.Name = "Node1";
      treeNode2.Text = "Node1";
      treeNode3.Name = "Node2";
      treeNode3.Text = "Node2";
      this.treeView1.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode1,
            treeNode2,
            treeNode3});
      this.treeView1.Size = new System.Drawing.Size(121, 97);
      this.treeView1.TabIndex = 3;
      this.treeView1.Visible = false;
      this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
      // 
      // Form1
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(760, 409);
      this.Controls.Add(this.treeView1);
      this.Controls.Add(this.button2);
      this.Controls.Add(this.listView1);
      this.Controls.Add(this.button1);
      this.Name = "Form1";
      this.Text = "Form1";
      this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.Button button1;
    private System.Windows.Forms.ListView listView1;
    private System.Windows.Forms.Button button2;
    private System.Windows.Forms.TreeView treeView1;

    #endregion


    public Form1()
    {
      InitializeComponent();
    }

    #region TreeView

    private void button2_Click(object sender, EventArgs e)
    {
      ToggleTreeView();
    }

    private void ToggleTreeView()
    {
      if (treeView1.Visible)
      {
        Controls.Remove(treeView1);
        treeView1.Visible = false;
      }
      else
      {
        Controls.Add(treeView1);
        treeView1.Size = new Size(300, 400);
        treeView1.Location = PointToClient(PointToScreen(new   System.Drawing.Point(button2.Location.X, button2.Location.Y + button2.Height)));
        this.treeView1.BringToFront();
        treeView1.Visible = true;
        treeView1.Select();

      }
    }

    private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
    {
      ToggleTreeView();
    }

    #endregion

    #region ListView

    private void button1_Click(object sender, EventArgs e)
    {
      ToggleListView();
    }

    private void ToggleListView()
    {
      if (listView1.Visible)
      {
        Controls.Remove(listView1);
        listView1.Visible = false;
      }
      else
      {
        Controls.Add(listView1);
        listView1.Size = new Size(300, 400);
        listView1.Location = PointToClient(PointToScreen(new System.Drawing.Point(button1.Location.X, button1.Location.Y + button1.Height)));
        this.listView1.BringToFront();
        listView1.Visible = true;
        listView1.Select();
      }
    }

    private void listView1_SelectedIndexChanged(object sender, EventArgs e)
    {
      if (listView1.Visible)
        ToggleListView();
    }

    #endregion        
  }
}
A: 

I can't explain why the form loses focus, but the problem seems to be the Controls.Remove(treeView1); line. If you remove the Controls.Remove and Controls.Add lines, then it seems to behave better.

Is there a reason why you are removing the treeView from the list of control? Just setting the visibility flag to false will cause the treeView to disappear after the user makes their selection.

EDIT:

In response to your comment: My guess is that after treeView1_AfterSelect is called, the TreeView is setting focus to itself. Which in your code is impossible because you've removed the control from the form.

To test this theory, I added a timer, replaced the code with:

private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
    timer1.Enabled = true;
    timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
    ToggleTreeView();
    timer1.Stop();
    timer1.Enabled = false;

}

Now it works fine. So I'm guessing that the TreeView is calling this.Focus after it has fired the AfterSelect event. (That is just a guess, maybe someone else knows more about the internals them me:) )

And the reason why this is working with the ListView, is that it does not set focus to itself after listView1_SelectedIndexChanged.

mlsteeves
But why does it work with the listview case?
A: 

Here is the problem and the fix.

http://stackoverflow.com/questions/569673/treeview-re-grabs-focus-on-ctrlclick