Проблема с производительностью при добавлении элементов управления на панель в C # - PullRequest
3 голосов
/ 07 июля 2011

Я создаю панель, а затем добавляю к ней несколько ярлыков / кнопок для формирования сетки. Проблема в том, что если я добавлю более 25х25 элементов на панель, произойдет ужасное снижение производительности. Я могу изменить размер формы в порядке, но когда я прокручиваю панель, чтобы увидеть все метки, которые программа отстает, метки / кнопки рвутся или мерцают, и иногда это может привести к тому, что программа не отвечает. Я попытался добавить элементы управления в «DoubleBufferedPanel», который я создал. Это, кажется, не имеет никакого эффекта. Что еще я мог сделать? Извините за такой большой листинг кода. Я не хотел терять чье-то время.

namespace GridTest
{
    public partial class Form1 : Form
    {
        private const int COUNT = 50;
        private const int SIZE = 50;
        private Button[,] buttons = new Button[COUNT, COUNT];
        private GridPanel pnlGrid;

        public Form1()
        {
            InitializeComponent();

            pnlGrid = new GridPanel();
            pnlGrid.AutoScroll = true;
            pnlGrid.Dock = DockStyle.Fill;
            pnlGrid.BackColor = Color.Black;

            this.Controls.Add(pnlGrid);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            int x = 0;
            int y = 0;
            int offset = 1;

            for (int i = 0; i < COUNT; i++)
            {
                for (int j = 0; j < COUNT; j++)
                {
                    buttons[i, j] = new Button();
                    buttons[i, j].Size = new Size(SIZE, SIZE);
                    buttons[i, j].Location = new Point(x, y);
                    buttons[i, j].BackColor = Color.White;

                    pnlGrid.Controls.Add(buttons[i, j]);

                    x = x + SIZE + offset;
                }

                x = 0;
                y = y + SIZE + offset;
            }
        }
    }
}

Также класс GridPanel:

namespace GridTest
{
    public class GridPanel : Panel
    {
        public GridPanel()
            : base()
        {
            this.DoubleBuffered = true;
            this.ResizeRedraw = false;
        }
    }
}

Ответы [ 2 ]

3 голосов
/ 07 июля 2011

Если вам необходимо добавить элементы управления во время выполнения, основываясь на некотором динамическом или изменяющемся значении, вы можете рассмотреть возможность создания изображения на лету и захвата событий щелчка мыши на его окне рисунка. Это было бы намного быстрее и иметь только один элемент управления, а не сотни. Вы потеряете некоторые функции кнопок, такие как анимация щелчка и другие автоматические свойства и события; но вы можете воссоздать большинство из них при создании изображения.

Это метод, который я использую, чтобы предложить пользователям возможность включать и выключать отдельные устройства из пула тысяч, когда местоположение в двухмерном пространстве имеет значение. Если расположение кнопок неважно, возможно, вам лучше предложить список элементов в виде списка или комбинированного списка, или, как предлагают другие ответы, в виде сетки данных со столбцами кнопок.

EDIT:

Пример, показывающий, как добавить графику с виртуальными кнопками. Очень простая реализация, но, надеюсь, вы получите идею:

Во-первых, некоторые начальные переменные в качестве предпочтений:

int GraphicWidth = 300;
int GraphicHeight = 100;
int ButtonWidth = 60;
int ButtonHeight = 20;
Font ButtonFont = new Font("Arial", 10F);
Pen ButtonBorderColor = new Pen(Color.Black);
Brush ButtonTextColor = new SolidBrush(Color.Black);

Генерация изображения:

Bitmap ControlImage = new Bitmap(GraphicWidth, GraphicHeight);
using (Graphics g = Graphics.FromImage(ControlImage))
{
    g.Clear(Color.White);
    for (int x = 0; x < GraphicWidth; x += ButtonWidth)
        for (int y = 0; y < GraphicHeight; y += ButtonHeight)
        {
            g.DrawRectangle(ButtonBorderColor, x, y, ButtonWidth, ButtonHeight);
            string ButtonLabel = ((GraphicWidth / ButtonWidth) * (y / ButtonHeight) + x / ButtonWidth).ToString();
            SizeF ButtonLabelSize = g.MeasureString(ButtonLabel, ButtonFont);
            g.DrawString(ButtonLabel, ButtonFont, ButtonTextColor, x + (ButtonWidth/2) - (ButtonLabelSize.Width / 2), y + (ButtonHeight/2)-(ButtonLabelSize.Height / 2));
        }
}
pictureBox1.Image = ControlImage;

И в ответ на Click событие pictureBox:

// Determine which "button" was clicked
MouseEventArgs em = (MouseEventArgs)e;
Point ClickLocation = new Point(em.X, em.Y);
int ButtonNumber = (GraphicWidth / ButtonWidth) * (ClickLocation.Y / ButtonHeight) + (ClickLocation.X / ButtonWidth);
MessageBox.Show(ButtonNumber.ToString());
1 голос
/ 07 июля 2011

Я думаю, что вы не сможете предотвратить мерцание, имея 625 кнопок (кстати, окна) на панели. Если такой макет является для вас обязательным, попробуйте использовать DataGridView, привязать его к ложному источнику данных, содержащему необходимое количество столбцов и строк, и создать в нем DataGridViewButtonColumns. Это должно работать намного лучше, чем ваш текущий результат ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...