none
Dúvida para identificar evento RRS feed

  • Pergunta

  • Olá, pessoal.

    Tenho um datagrid no qual quando uma linha é selecionada, exibo em um richtextbox o conteúdo rtf de um campo do banco de dados.

    Notei que quando puxo arquivos maiores, há um delay para a exibição do mesmos no richtextbox e que também na mudança de seleção da linha no datagrid. Daí eu queria colocar uma splash screen ou um simples label informando que o texto está sendo carregado.

    Porém, não sei em qual evento de qual controle colocar para aparecer o label. Já tentei Enter, click, Keypress, mas o label que criei não aparece. Sei que assim que o texto aparece no richtextbox eu coloco um label1.hide(). Problema é que em que evento e em qual controle exibir o label1.show(), já que quando há o delay parece que nenhum evento responde até o carregamento do richtextbox e a mudança de linha do datagrid.

    Alguém pode me ajudar? Grato.

    terça-feira, 10 de junho de 2014 18:50

Respostas

  • Faça o seguinte então:

    no datagridview, adicione o evento CellContentDoubleClick

    tenha em mente, que ele seria equivalente ao meu button.

    codigo comentado, alguma duvida, tentarei te ajudar.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace manipulador_de_arquivos
    {
        public partial class Form1 : Form
        {
    
            RichTextBox rich = new RichTextBox(); // aqui é um rich virtual, nao vai aparecer no form
            // mas toda e qualquer estilização ele vai carregar
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                
            }
    
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                Thread.Sleep(5000); // simulando seu datagridview, no caso o delay
                // como vc vai por o texto formatado, se atente ao meu richtext virtual que foi declarado no meu formulário
                // ai aqui, vc atribui o valor para ela
                rich.Text = "seria seu rich text";
                // aqui não manipula NADA do form, nenhum componente diretamente, apenas as variaveis globais do formulário
            }
    
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                richTextBox1.Text = rich.Text;
                // aqui, vc passa para o componente, o valor da variavel que vc puxou no processamento no DoWork
                // pois aqui ja está pronto
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                richTextBox1.Text = "carregando"; // avisa que está carregando o formulário
                backgroundWorker1.RunWorkerAsync(); // manda executar em thread paralela
            }
        }

    quinta-feira, 12 de junho de 2014 14:42

Todas as Respostas

  • Olá Denis Valjean,
    Você pode usar a função em uma thread secundária.

    Pode informar o seu código atual para que eu consiga montar e explicar o novo código?

    terça-feira, 10 de junho de 2014 19:15
  • não faça drásticas alterações! muito simples resolver seu problema.

    adicione o componente BackGroundWorker

    com ele, vc utilizará 2 eventos

            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                // alguma função aqui, ela é executada fora da thread principal, então não trava o formulário
            }
    
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                // quando completado, vem para cá, aqui vc consegue manipular qualquer componente do seu form
            }

    e para chama-lo é assim:

    backgroundWorker1.RunWorkerAsync();

    terça-feira, 10 de junho de 2014 19:25
  • O código é esse. Estava justamente tentando executar outra thread mas ainda não consegui. Agradeço a ajuda!

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Data.SQLite;
    using System.Threading; 
    
    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
    
            static Thread Evento = null; 
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
    
    
    
              
    
    
    
              
                //Conexão ao Banco de Dados SqLite
                const string filename = @"D:\Banco\teste.s3db";
                const string sql = "select * from table1;";
                var cone = new SQLiteConnection("Data Source=" + filename + ";Version=3;");
                try
                {
                    cone.Open();
    
                    DataSet ds = new DataSet();
                    var da = new SQLiteDataAdapter(sql, cone);
                   
                    da.Fill(ds);
                    dataGridView1.DataSource = ds.Tables[0].DefaultView;
                    dataGridView1.Columns["Texto"].Visible = false;
                    
                }
                catch (Exception)
                {
                    throw;
                }
    
            }
    
    
    
    
    
            private void dataGridView1_RowEnter_1(object sender, DataGridViewCellEventArgs e)
            {
                      
               
                if (e.RowIndex >= 0)
                {
                    DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
                    richTextBox1.Rtf = row.Cells["Texto"].Value.ToString();
                   // label1.Hide();
                }        
               
            }
    
         
            private void Form1_KeyDown(object sender, KeyEventArgs e)
    
            {
    
                if (e.KeyCode == Keys.Up)
                {
    
                    Evento = new Thread(new ThreadStart(Mostra));
                    Evento.Start();
    
                    //Mostra();  
                }
            }
    
    
    
    
            static public void Mostra()
            {
                Form1 obj = new Form1();
                obj.label1.Show();
            }
    
    
    
    
    
        }
    }
    

    terça-feira, 10 de junho de 2014 20:05
  • Da para você fazer da seguinte maneira, criar um novo Form, chamado FormSplash, tanto faz, e chamar a função Show() dele antes de começar a pegar os dados da row para o rtf e depois a função Hide() depois que terminar...

    Exemplo

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Data.SQLite;
    using System.Threading; 
    
    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
            private FormSplash obj = new FormSplash();
    	
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                //Conexão ao Banco de Dados SqLite
                const string filename = @"D:\Banco\teste.s3db";
                const string sql = "select * from table1;";
                var cone = new SQLiteConnection("Data Source=" + filename + ";Version=3;");
                try
                {
                    cone.Open();
    
                    DataSet ds = new DataSet();
                    var da = new SQLiteDataAdapter(sql, cone);
                   
                    da.Fill(ds);
                    dataGridView1.DataSource = ds.Tables[0].DefaultView;
                    dataGridView1.Columns["Texto"].Visible = false;
                    
                }
                catch (Exception)
                {
                    throw;
                }
    
            }
    		
            private void dataGridView1_RowEnter_1(object sender, DataGridViewCellEventArgs e)
            {
                if (e.RowIndex >= 0)
                {
    		obj.Show();
                    DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
                    richTextBox1.Rtf = row.Cells["Texto"].Value.ToString();
    		obj.Hide();
                }        
            }
         
            private void Form1_KeyDown(object sender, KeyEventArgs e)
            {
    
            }
        }
    }

    Ai nesse novo formulário, você coloca uma Label com o Texto "Carregando".. ou algo do tipo.

    terça-feira, 10 de junho de 2014 20:31
  • Como ficaria o meu código com um backgroundworker ou thread? Tentei colocar aqui mas está dando erro... Diz que o backgroundworker está ocupado e não pode realizar tarefas simultâneas. Eu gostaria que ele fosse executado a cada Rowenter, e não só uma vez.
    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
    
    
    
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
               
                Mostra();
            }
    
    
    
    
    
    
      
            public Form1()
            {
                InitializeComponent();
            }
        
            private void Form1_Load(object sender, EventArgs e)
            {
    
              
      
                //Conexão ao Banco de Dados SqLite
                const string filename = @"D:\Banco\teste.s3db";
                const string sql = "select * from table1;";
                var cone = new SQLiteConnection("Data Source=" + filename + ";Version=3;");
              
                     
                try
                {
                   
                    cone.Open();
                    DataSet ds = new DataSet();
                    var da = new SQLiteDataAdapter(sql, cone);
                    da.Fill(ds);
                    dataGridView1.DataSource = ds.Tables[0].DefaultView;
                    dataGridView1.Columns["Texto"].Visible = false;
    
                }
                catch (Exception)
                {
                    throw;
                }
               
            }
    
    
          
    
            private void dataGridView1_RowEnter_1(object sender, DataGridViewCellEventArgs e)
            {
    
    
                backgroundWorker1.RunWorkerAsync();
    
                if (e.RowIndex >= 0)
                {
                    
                    DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
                    richTextBox1.Rtf = row.Cells["Texto"].Value.ToString();
                    //label1.Hide();
                }        
               
            }
    
         
    
           static public void Mostra()
            {
                Form1 Form1 = new Form1(); 
                Form1.label1.Show();
            }
    
    
        }
    }
    


    quarta-feira, 11 de junho de 2014 14:34
  • Olá, você poderia montar o último código que passei e me explicar como usar uma nova htread ou background worker? Tudo que eu tento dá um erro ou não faz o que eu quero!
    quarta-feira, 11 de junho de 2014 20:35
  • namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
    	    DataSet ds;
    	
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
               
                Mostra();
            }
    		
    		private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                dataGridView1.DataSource = ds.Tables[0].DefaultView;
                dataGridView1.Columns["Texto"].Visible = false;
            }
      
            public Form1()
            {
                InitializeComponent();
            }
        
            private void Form1_Load(object sender, EventArgs e)
            {            
               backgroundWorker1.RunWorkerAsync();
            }
    
            private void dataGridView1_RowEnter_1(object sender, DataGridViewCellEventArgs e)
            {
    
                if (e.RowIndex >= 0)
                {
                    
                    DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
                    richTextBox1.Rtf = row.Cells["Texto"].Value.ToString();
                }        
               
            }
    
    
           static public void Mostra()
            {
                //Conexão ao Banco de Dados SqLite
                const string filename = @"D:\Banco\teste.s3db";
                const string sql = "select * from table1;";
                var cone = new SQLiteConnection("Data Source=" + filename + ";Version=3;");       
                try
                {
                    cone.Open();
                    ds = new DataSet();
                    var da = new SQLiteDataAdapter(sql, cone);
                    da.Fill(ds);
                    
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
    }

    quinta-feira, 12 de junho de 2014 11:21
  • Não aparecem os dados no datagrid quando do RunWorkerCompleted.. Queria apenas que o label "carregando" aparecesse em cada RowEnter.

    Fica como se o datagrid estivesse carregando indefinidamente.

    quinta-feira, 12 de junho de 2014 12:15
  • cara, não consigo acompanhar seu raciocinio logico.

    o maximo que posso fazer é montar um escopo de thread non-safe e vc adapitar.

    te ajudaria ter multiplas threads controlando um mesmo formulário e seus componentes?

    assim, seria possivel ter diversas funções rodando ao mesmo tempo sem travar o formulário.

    quinta-feira, 12 de junho de 2014 13:06
  •  Não se preocupe, eu sou novo no C# e provavelmente o meu raciocínio deve estar errado.

    O que queria e tentei fazer de início era o que fazia numa programação sequencial: assim que eu entrasse num célula do datagrid (RowEnter) eu exibiria um label "carregando". Quando o texto rtf do richtextbox terminasse de ser carregado esse label sumiria, mais ou menos isso:

     private void dataGridView1_RowEnter_1(object sender, DataGridViewCellEventArgs e)
            {
             label1.Show();
                if (e.RowIndex >= 0)
                {
                    DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
                    richTextBox1.Rtf = row.Cells["Texto"].Value.ToString();

              label.1Hide();

                }

            }

    Mas notei que o evento RowEnter só dispara quando o Richtext é totalmente preenchido. Tentei mudar de RowEnter para Keypress, imaginando que assim que apertasse, por exemplo, a tecla UP, o label apareceria antes do carregamento completo do richtextbox. Acontece que nada disso funcionou. Funciona se eu colocar um Messagebox. Aí sim, assim que aperto a tecla Up a Messagebox aparece antes do texto carregar, mas com o label nada acontece. Por que? Só queria entender isso e achar um jeito do label "carregando" aparecer assim que uma linha do datagrid for selecionada, ou clicada e este mesmo label sumir assim que o texto do richtextbox a que se refere esta linha estiver totalmente carregado.

    É isso que ainda não pesquei. Não se se me entendeu.


    Só acrescentar uma coisa que notei. Quando testando com o Messagebox, este apareceu 3 vezes antes do Form Load usando o evento RowEnter. Não teria que aparecer só uma vez?, pois o Form já abre com o item 1 do datagrid selecionado. Por que esse evento aconteceu mais vezes?
    quinta-feira, 12 de junho de 2014 13:23
  • Faça o seguinte então:

    no datagridview, adicione o evento CellContentDoubleClick

    tenha em mente, que ele seria equivalente ao meu button.

    codigo comentado, alguma duvida, tentarei te ajudar.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace manipulador_de_arquivos
    {
        public partial class Form1 : Form
        {
    
            RichTextBox rich = new RichTextBox(); // aqui é um rich virtual, nao vai aparecer no form
            // mas toda e qualquer estilização ele vai carregar
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                
            }
    
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                Thread.Sleep(5000); // simulando seu datagridview, no caso o delay
                // como vc vai por o texto formatado, se atente ao meu richtext virtual que foi declarado no meu formulário
                // ai aqui, vc atribui o valor para ela
                rich.Text = "seria seu rich text";
                // aqui não manipula NADA do form, nenhum componente diretamente, apenas as variaveis globais do formulário
            }
    
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                richTextBox1.Text = rich.Text;
                // aqui, vc passa para o componente, o valor da variavel que vc puxou no processamento no DoWork
                // pois aqui ja está pronto
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                richTextBox1.Text = "carregando"; // avisa que está carregando o formulário
                backgroundWorker1.RunWorkerAsync(); // manda executar em thread paralela
            }
        }

    quinta-feira, 12 de junho de 2014 14:42
  • Valeu cara. Ainda não funcionou direito aqui. Funciona de vez em quando só no primeiro registro do datagrid, mas sei que é culpa minha. Eu encontrei que não funciona no RowEnter porque esse evento é acionado quando da construção do datagrid, então quando uso Rowenter fala que o worker já estava rodando. Parece que tem que lidar com handlers, mas isto ainda está muito complexo pra mim. Vou estudar com calma. Valeu e obrigado pela ajuda!!
    quinta-feira, 12 de junho de 2014 19:54