progressBar и Marquee

228
04 апреля 2018, 08:12

Не работает прогресс бар типа Marquee. По нажатию кнопку использую код:

        progressBar.Visible = true;
        progressBar.Style = ProgressBarStyle.Marquee;
        progressBar.MarqueeAnimationSpeed = 30;

затем после всех запросов в базу в конце процедуры:

       progressBar.Style = ProgressBarStyle.Continuous;
       progressBar.MarqueeAnimationSpeed = 0;
       progressBar.Visible = false;

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

    private void btnOK_Click(object sender, EventArgs e)
    {
        progressBar.Style = ProgressBarStyle.Marquee;
        progressBar.MarqueeAnimationSpeed = 30;
        progressBar.Visible = true; 
        string dt = dtPicker.Value.Date.ToString("dd.MM.yyyy");
        string str_item = "";
        foreach (object itemChecked in cklstBox.CheckedItems)
        { 
            if (str_item != "")
            {
                str_item += ", ";
            }
            str_item += "'" + itemChecked.ToString() + "'";              
        }
        if (str_item == "") 
        {
            MessageBox.Show("Не выбрано ни одной компании!", "Ошибка!",
                             MessageBoxButtons.OK,
                             MessageBoxIcon.Error);
            this.DialogResult = System.Windows.Forms.DialogResult.None;
            return;
        }
        string sqlForCnt = "SELECT * FROM dbo.Clients WHERE ClientCode IN (" + str_item + ")";
        string odbccon = this.ConnectionStr;
        string filename = @"5.docx";
        SqlConnection _con = new SqlConnection(odbccon);
        _con.Open();            
        DataTable dtb;
        //DataSet ds;
        SqlDataAdapter adapter; 
        dtb = new DataTable();
        using (adapter = new SqlDataAdapter(sqlForCnt, _con))
        {
            adapter.Fill(dtb);
        }
        _con.Close();
        foreach (System.Data.DataRow rw in dtb.Rows)
        {
            try
            {
               string fName = RiskReportPath + @"\";
                if (!Directory.Exists(fName + dt))
                {
                    Directory.CreateDirectory(fName + dt);
                }
                string fout = fName + dt + @"\" + reportfilename + @".docx";
         //здесь идут куча запросов в базу и формирование xml
                rtfgen r = new rtfgen(filename, (string)rw[0], dt, klientcode.Replace("_", "").Replace("-", "") + dt.Replace(".", ""), odbccon);
                if (File.Exists(fout))
                {
                    File.Delete(fout);
                }
                r.WriteTo(fout);
                progressBar.MarqueeAnimationSpeed = 0;
                MessageBox.Show("Отчет по рискам сформирован успешно.", "Отчет по рискам!",
                             MessageBoxButtons.OK,
                             MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                progressBar.Style = ProgressBarStyle.Continuous;
                progressBar.MarqueeAnimationSpeed = 0;
                progressBar.Visible = false;
                throw ex;
            }
        }
    }
Answer 1

Проблема WinForms, что она "учит" писать жуткую лапшу. Позволю себе пару замечаний. Начнем по порядку.

1) Вот это код проверки чекбоксов

string str_item = "";
foreach (object itemChecked in cklstBox.CheckedItems)
{ 
    if (str_item != "")
    {
        str_item += ", ";
    }
        str_item += "'" + itemChecked.ToString() + "'";              
}

Лучше переписать как вызов метода и получение результата

string clientCodes = GetClientCodes();

тогда вместо вашего if (str_item == "")будет проверка такая

if (String.IsNullOrEmpty(clientCodes)) {...}

2) Всю работу по запросам к БД нужно выделять в отдельный класс, а не лепить, так сказать, по месту имения. Создайте отдельный класс Repository, напишите там всю логику работы с данными в БД (там должны быть методы типа получить всех клиентов public List<Client> GetAllClients(), сохранить нового клиента public void AddClient(Client client) и т.д). Тогда в форме будет достаточно создать приватное поле

private readonly Repository _repo;

и в конструкторе формы его проинициализировать

_repo = new Repository();

и далее можно получать и сохранять данные в БД через методы этого класса, например

List<Client> clients = _repo.GetClientsByCodes(clientCodes); 

3) Вот в этом цикле foreach (System.Data.DataRow rw in dtb.Rows) лежит очень злое**** код. Его нужно разбить на отдельные методы. try/catch должно быть снаружи этого цикла, а не как у вас внутри, надо добавить блок finally в котором как раз и делать возвращение состояния прогрессбара к исход. состоянию

try
{
    foreach (var client in clients)
    {
        string fout = GetFileName();
        if (File.Exists(fout))
        {
            File.Delete(fout);
        }
        //!!!Классы нужно именовать правильно, с заглавной буквы, а не как у вас
        rtfgen r = new rtfgen(filename,.....
        //ну и далее
    }
}
catch(...)
{
}
finally
{
    progressBar.Style = ProgressBarStyle.Continuous;
    progressBar.MarqueeAnimationSpeed = 0;
    progressBar.Visible = false;
}

4) Для того, чтобы освободить, не замораживать UI программы нужно использовать async/await и Task.Run(). Тогда всю работу с циклом нужно вынести в отдельный метод типа SaveClientsRtf() и тогда вызывать в блоке try так

try
{
    await Task.Run(() => SaveClientsRtf(clients));
}
catch...finally...

Подробнее как работать с асинхрон. кодом см. пример

READ ALSO
Убрать switch размером с гору Эверест

Убрать switch размером с гору Эверест

В общем, есть switch длиной с Эверест, как бы вы избавились от него, кроме как записывать это в Dictionary?

214
Хранение делегатов в Dictionary

Хранение делегатов в Dictionary

Здравствуйте, подскажите как бы Вы написали следующий функционал, хочу узнать как можно реализовать это более эффективно, спасибо

210
SQL-инъекции, как бороться?

SQL-инъекции, как бороться?

Доброго времени сутокВ разрабатываемом приложении работа с данными БД происходит через запросы, формируемые следующим образом (например...

211
Частое пробуждение Alarm Manager Google Play

Частое пробуждение Alarm Manager Google Play

Подскажите что это значит (скрин), и какие способы решения есть, и соответственно из-за чего это может происходить ? Используется реклама Kidoz,...

191