Есть ли лучший способ заставить значения полосы прокрутки для определенных приращений и привязать значения к текстовому полю (C #)? - PullRequest
0 голосов
/ 13 мая 2018

У меня есть настройка в моем приложении, которая требует любое значение между 24 и 65520, которое должно быть равномерно делено на 24. Я решил реализовать это с горизонтальной полосой прокрутки и текстовым полем, которое показывает текущее значение полосы прокрутки, и может иметьзначение, введенное в него вручную (которое затем устанавливает значение полосы прокрутки).Полоса прокрутки имеет минимум = 24, максимум = 65520, маленькие и большие приращения = 1. Значение по умолчанию при запуске приложения - 960. В итоге мне пришлось использовать несколько обработчиков событий как для текстового поля, так и для полосы прокрутки, и даже до сих порне работал идеально.Моя первая в основном рабочая попытка была такой:

    private void hScrollBar_TicksPerQuarter_Scroll(object sender, ScrollEventArgs e)
    {
        int NewValue = e.NewValue;

        if (e.Type != ScrollEventType.EndScroll)
        {
            if (e.NewValue < e.OldValue)
            {
                NewValue = e.NewValue - (e.NewValue % 24);
            }
            else if (e.NewValue > e.OldValue)
            {
                NewValue = e.NewValue + (e.NewValue % 24 == 0 ? 0 : 24 - (e.NewValue % 24));
            }

            txtTicksPerQuarter.Text = NewValue.ToString();
        }
        else
        {
            hScrollBar_TicksPerQuarter.Value = NewValue;
        }
    }

    private void hScrollBar_TicksPerQuarter_ValueChanged(object sender, EventArgs e)
    {
        if (hScrollBar_TicksPerQuarter.Value.ToString() != txtTicksPerQuarter.Text)
        {
            hScrollBar_TicksPerQuarter.Value = Convert.ToInt32(txtTicksPerQuarter.Text);
        }
    }

    private void txtTicksPerQuarter_Leave(object sender, EventArgs e)
    {
        TrySetTicksPerQuarter();
    }

    private void txtTicksPerQuarter_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
            TrySetTicksPerQuarter();
    }

    private void TrySetTicksPerQuarter()
    {
        bool useOldValue = false;
        int TicksPerQuarter_OldValue = hScrollBar_TicksPerQuarter.Value;
        int TicksPerQuarter = 0;
        if (Int32.TryParse(txtTicksPerQuarter.Text, out TicksPerQuarter))
        {
            if (TicksPerQuarter % 24 == 0)
            {
                hScrollBar_TicksPerQuarter.Value = TicksPerQuarter;
            }
            else
            {
                useOldValue = true;
                MessageBox.Show("Must enter a value that is a multiple of 24, with a minimum of 24 and a maximum of 65520.", "Invalid TicksPerQuarter", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
        else
        {
            useOldValue = true;
        }

        if (useOldValue)
            txtTicksPerQuarter.Text = TicksPerQuarter_OldValue.ToString();
    }

Это работает довольно хорошо, если я введу значение в текстовое поле и оставлю поле или нажму Enter, оно соответствующим образом обновит полосу прокрутки, и если значениене является правильным кратным 24, он просто сбрасывает себя к последнему действительному значению и отображает сообщение пользователю, указывающее проблему.Прокрутка полосы прокрутки обновляет текстовое поле в режиме реального времени во время прокрутки, и все в основном работает.Проблема в том, что при нажатии и перетаскивании полосы прокрутки момент, когда вы позволяете, приводит к скачку значения (обычно это пара сотен или около того, в любом направлении).Не зная, почему это происходило, я начал экспериментировать с изменениями события «Прокрутка» на полосе прокрутки, чтобы посмотреть, смогу ли я исправить это, поэтому при отпускании полосы прокрутки после ее перетаскивания значение остается на том же уровне, что и на момент его отпускания.,Потребовалось много экспериментов, в том числе некоторые радикальные изменения всего, что даже не работало, а также кода, который я выложил выше, но в конечном итоге лучшее, что я мог получить, - это сохранить весь код выше в других событиях, ипросто измените событие прокрутки на следующее:

    ScrollEventType[] IncrementScrollEvents = new ScrollEventType[] { ScrollEventType.LargeIncrement, ScrollEventType.SmallIncrement, ScrollEventType.Last };
    ScrollEventType[] DecrementScrollEvents = new ScrollEventType[] { ScrollEventType.LargeDecrement, ScrollEventType.SmallDecrement, ScrollEventType.First };
    private void hScrollBar_TicksPerQuarter_Scroll(object sender, ScrollEventArgs e)
    {
        int NewValue = e.NewValue;

        if (IncrementScrollEvents.Contains(e.Type))
        {
            NewValue = e.NewValue + (e.NewValue % 24 == 0 ? 0 : 24 - (e.NewValue % 24));
        }
        else if (DecrementScrollEvents.Contains(e.Type))
        {
            NewValue = e.NewValue - (e.NewValue % 24);
        }
        else if (e.Type == ScrollEventType.ThumbTrack)
        {
            if (e.NewValue < e.OldValue)
            {
                NewValue = e.NewValue - (e.NewValue % 24);
            }
            else if (e.NewValue > e.OldValue)
            {
                NewValue = e.NewValue + (e.NewValue % 24 == 0 ? 0 : 24 - (e.NewValue % 24));
            }
        }
        else if (e.Type == ScrollEventType.EndScroll)
        {
            hScrollBar_TicksPerQuarter.Value = NewValue;
        }
        else
        {
            return;
        }

        txtTicksPerQuarter.Text = NewValue.ToString();
    }

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

Я надеялся, что есть лучший способ сделать это, и с точки зрения функциональности, будучи немного более совершенным, чем сейчас, и, возможно, даже с точки зренияобщая сложность кода.Я не ожидал, что для этого потребуется написать код в 4 разных событиях на 2 элементах управления, но, возможно, в конце концов нет лучшего способа?

РЕДАКТИРОВАТЬ 1:

У меня былоидея использовать приращения 1 и мин / макс 1-2730 вместо 24-65520, а затем вместо того, чтобы выполнять математику и проверку и вручную устанавливать значение полосы прокрутки, чтобы она была кратна 24, я вместо этого просто умножу ее действительноезначение на 24, чтобы получить полезное значение и отображаемое значение для текстового поля.Этот код теперь идентичен по функциональности тому, что я имел выше, с гораздо меньшей сложностью.Я также переместил окно с предупреждением о недопустимой записи в текстовое поле, чтобы оно отображало сообщение, даже когда пользователь вводит что-то, что даже не может быть преобразовано в целое число:

    private void hScrollBar_TicksPerQuarter_Scroll(object sender, ScrollEventArgs e)
    {
        txtTicksPerQuarter.Text = (e.NewValue * 24).ToString();
    }

    private void txtTicksPerQuarter_Leave(object sender, EventArgs e)
    {
        TrySetTicksPerQuarter();
    }

    private void txtTicksPerQuarter_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
            TrySetTicksPerQuarter();
    }

    private void TrySetTicksPerQuarter()
    {
        bool useOldValue = false;
        int TicksPerQuarter_OldValue = hScrollBar_TicksPerQuarter.Value;
        int TicksPerQuarter = 0;
        if (Int32.TryParse(txtTicksPerQuarter.Text, out TicksPerQuarter))
        {
            if (TicksPerQuarter % 24 == 0)
            {
                hScrollBar_TicksPerQuarter.Value = (TicksPerQuarter / 24);
            }
            else
            {
                useOldValue = true;
            }
        }
        else
        {
            useOldValue = true;
        }

        if (useOldValue)
        {
            MessageBox.Show("Must enter a value that is a multiple of 24, with a minimum of 24 and a maximum of 65520.", "Invalid TicksPerQuarter", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            txtTicksPerQuarter.Text = (TicksPerQuarter_OldValue * 24).ToString();
        }
    }

Полоса прокрутки все еще время от времени скачет, когдаВы отпускаете кнопку мыши, когда перетаскиваете ее влево и вправо.У меня до сих пор нет решения этой конкретной проблемы, разве я не могу исправить это из-за того, как мышь и полоса прокрутки играют друг с другом?

1 Ответ

0 голосов
/ 13 мая 2018

Я только что создал небольшое демонстрационное приложение WinForms, используя только одну полосу прокрутки (hScrollbar1) и метку (Label1).

Создал обработчик события Load формы и добавил следующий код:

hScrollBar1.Minimum = 1;
hScrollBar1.Maximum = 65520 / 24;
hScrollBar1.Value = 960 / 24;
hScrollBar1.LargeChange = 1;

Создал обработчик события ValueChanged hScrollBar1 и добавил следующий код:

label1.Text = (hScrollBar1.Value * 24).ToString();

Кажется, что у меня так работает нормально.Не уверен, смогу ли я заставить его работать при использовании пошаговых значений 24 в настройках свойства полосы прокрутки ... Извините за это ...

Редактировать: Только что увидел ваш собственный комментарий.Согласен.:)

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