Search code examples
c#winformspropertygrid

PropertyGrid causes unintended scrolling when Form.AutoScroll=true


I'm having an issue with a PropertyGrid control in my .NET Forms application.
I try to put a ProperyGrid on the Form which has AutoScroll property set to true.
When the PropertyGrid is located inside the display area of the Form, it's OK.
But, when the PropertyGrid is located outside the display area of Form, PropertyGrid causes unintended scrolling.

It is difficult for me to describe this issue in text.
Here is the code to reproduce this issue.

using System.Drawing;
using System.Windows.Forms;

namespace PropertyGridAutoScrollProblem
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            //InitializeComponent();

            Control[] controls = new Control[]
            {
                new TextBox(),
                new RadioButton(),
                new ListBox(),
                new ListView(),
                new PropertyGrid() { SelectedObject = this },
                new DataGridView(),
            };

            var tabControl = new TabControl();
            tabControl.Size = new Size(400, 400);
            tabControl.Location = new Point(50, 50);
            this.Controls.Add(tabControl);

            foreach (var control in controls)
            {
                control.Location = new Point(50, 250);
                control.Size = new Size(200, 100);

                var tabPage = new TabPage(control.GetType().Name);
                tabPage.Controls.Add(control);
                tabControl.Controls.Add(tabPage);
            }

            this.AutoScroll = true;
            this.ClientSize = new Size(400, 200);
        }
    }
}

This program has some tabs.
Each tab contains one control related to its tab name and located outside the display area of Form.
If you click any tabs except "PropertyGrid", scrolling will not be occurred.
But if you click "PropertyGrid" tab, unintended scrolling will be occurred.

These are the screenshots of this program.
The last (right-bottom) screenshot is after clicking "PropertyGrid".

Is there any way to avoid unintended scrolling?

Updated 1:

Here is the screenshots I tried and expected.

Updated 2:

@RezaAghaei Thank you for your solution but it is not perfect for me..
My expected result is "no scrolling occurred".

Here is the screenshots I tried and expected.

Updated 3:

@RezaAghaei Thank you for your reply.

In my understanding, when we deselect the form and select it again, the form scrolls to show the top-left coordinate of a focused control by AutoScroll default behavior.
And, if I click the second tab, the tab control will be focused.
I think it is natural for me.

If I click any control on a tabpage after selecting the tab, the clicked control will be focused and the tab control will lost focus.
In this situation, if I deselect the form and select it again, the form will scroll to show the top-left coordinate of the clicked control (not tab control).


Solution

  • The problem

    This will happen for all containers like TabPage or Panel or Form to bring PropertyGrid into view and the behavior is because of this code in PropertyGrid constructor, line 259:

    SetActiveControlInternal(gridView);
    

    And the solution is setting the active control of form or when you need scroll to container to specific location.

    You may need both of fixes if both form and tab page scrolled.

    When TabPage scrolled

    When your tab page scrolled, to get rid of this problem you can scroll to (0,0) when the selected tab changes:

    private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
    {
        tabControl.SelectedTab.AutoScrollPosition = new Point(0, 0);
    }
    

    When Form scrolled

    If the form scrolled, you can scroll it to show tab pages again:

    private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
    {
        this.ScrollControlIntoView(tabControl);
    }
    

    Note

    • Also you can limit this correction to your specific tab using:
    //Suppose tabPage2 is the name of tab page that contains the PropertyGrid
    if (tabControl.SelectedTab == this.tabPage2)
    

    Your Expected Result

    I think solving the problem is layout-dependent and for your specific case I used this code to get your expected result:

    tabControl.SelectedIndexChanged += (sender, e) =>
    {
        if (tabControl.SelectedIndex == 4)
        {
            this.AutoScrollPosition = new Point(0,0);
            tabControl.SelectedTab.AutoScrollPosition = new Point(0, 0);
        }
    };
    

    But I think using below code is more natural solution, because when using the above code, if you minimize and restore the windows, you will get the result of below code.

    tabControl.SelectedTab.AutoScrollPosition = new Point(0, 0);
    this.ScrollControlIntoView(tabControl);