none
textbox com databinding - leitura de serial - wpf - falha update RRS feed

  • Pergunta

  • Fiz um código simples para atualizar uma textbox com dados lidos via serial.

    <Window x:Class="WpfSerialTestApplication.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="236" Width="525">
        
            <Canvas x:Name="MainCanvas"
                Height="178" HorizontalAlignment="Left" Margin="12,12,0,0" VerticalAlignment="Top" Width="482">
            <Button Canvas.Left="20" Canvas.Top="21" Content="Ler" Height="23" Name="btnStart" Width="75" Click="btnStart_Click" />
            <Button Canvas.Left="124" Canvas.Top="21" Content="Parar" Height="23" Name="btnStop" Width="75" Click="btnStop_Click" />
            <TextBox Canvas.Left="28" Canvas.Top="61" Height="79" Name="txtDados" Width="391"
                     Text="{Binding Path=Texto}"/>
        </Canvas>
    </Window>

    c# code behind:

    SerialPort serial = new SerialPort("COM1", 4800, Parity.None,8,StopBits.One);
            delegate void UpdateUiTextDelegate(string t);
           
            SerialVO myObj = new SerialVO();
            
            public MainWindow()
            {
                InitializeComponent();            
                myObj.Texto = "teste";
                this.MainCanvas.DataContext = myObj;
            }
    
            private void btnStart_Click(object sender, RoutedEventArgs e)
            {
                serial.ReadTimeout = 200;
                serial.WriteTimeout = 50;
                serial.Open();
                myObj.Texto = "teste"; 
                serial.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Recieve);
               
               // WriteSerialData();
            }
    
            private void WriteSerialData()
            {
                string dados = "teste de envio";
               
                if (serial.IsOpen)
                {
                    try
                    {                    
                            serial.Write(dados);
                            Thread.Sleep(10);                    
                    }
                    catch (Exception ex)
                    {
                        txtDados.Text = ex.Message;
                    }
                }
            }
    
            // get data
            private void Recieve(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
                // Collecting the characters received to our 'buffer' (string).
               string recieved_data = serial.ReadExisting();
               
               this.Dispatcher.BeginInvoke(new UpdateUiTextDelegate(WriteData), System.Windows.Threading.DispatcherPriority.Send, recieved_data);
               myObj.Texto = recieved_data;           
            }      
    
            private void btnStop_Click(object sender, RoutedEventArgs e)
            {
                if (serial.IsOpen)
                {
                    serial.Close();
                    
                }
                myObj.Texto = "parado";
            }

    classe do objeto source:

      public class SerialVO : INotifyPropertyChanged
        {
            private string texto;
    
            public string Texto
            {
                get { return texto; }
                set
                {
                    texto = value;
                      this.OnPropertyChanged("Texto");
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            #region INotifyPropertyChanged Members
    
            void OnPropertyChanged(string propName)
            {
                if (this.PropertyChanged != null)
                    this.PropertyChanged(
                        this, new PropertyChangedEventArgs(propName));
            }
    
            #endregion
        }

    Quando inicio a leitura (tenho um gps na serial), o textbox atualiza perfeitamente.

    o problema: ao clicar em Parar e novamente em Ler, o textbox não atualiza mais.

    any ideas?


    Chris

    terça-feira, 3 de setembro de 2013 18:19

Respostas

  • staticvoid Main(string[] args) { // create the object DataCache cache = new DataCache();   // create the delegate CacheFlusher flusher = new CacheFlusher(cache.FlushToDisk);   // call the delegate asynchronously flusher.BeginInvoke("data.dat", new AsyncCallback(CallbackMethod), flusher);   // wait to exitConsole.WriteLine("Press enter to exit"); Console.ReadLine(); }   staticvoid CallbackMethod(IAsyncResult result) { // get the delegate that was used to call that// method CacheFlusher flusher = (CacheFlusher) result.AsyncState;   // get the return value from that method callint returnValue = flusher.EndInvoke(result);   Console.WriteLine("The result was " + returnValue); }

    Tenta fazer parecido com o código acima, ai toda vez que terminar a executação do BeginInvoke ele vai retornar o valor para

    metodo CallbackMethod, neste metodo vc seta o retorno.

    quarta-feira, 4 de setembro de 2013 17:07

Todas as Respostas

  • <TextBox Canvas.Left="28" Canvas.Top="61" Height="79" Name="txtDados" Width="391" Text="{Binding Path=Texto,UpdateSourceTrigger=PropertyChanged}"/>


    terça-feira, 3 de setembro de 2013 18:27
  • já tinha usado isso, porém o comportamento é o mesmo: após parar, quando inicia leitura, a informação na interface não exibe de forma correta, fica branco o textbox, ou pisca extremamente rápido a informação, quase imperceptível.

    vou tentar achar outra abordagem.


    Chris

    quarta-feira, 4 de setembro de 2013 12:25
  • Está chegando valor nessa variável ?
    string recieved_data
    quarta-feira, 4 de setembro de 2013 13:18
  • sim, não há problema com a leitura dos dados.

    Em debug, consigo ver sempre o valor. identifiquei que a frequencia de leitura pode estar alta demais, deduzo isso pq com um Thread.Sleep(1000) após essa atribuição, da recieved_data, consigo ver os dados exibidos.

    Imagino que tenho que gerenciar isso. como disse, a implementação original comporta-se de modo que pisca a informação, numa fração de segundo. No 1o. start vai bem, mas depois nao fica legal.

    nao há erros ou exceções. to vendo como ajustar o uso de Dispatcher.BeginInvoke(..) pra corrigir o comportamento.


    Chris

    quarta-feira, 4 de setembro de 2013 16:51
  • staticvoid Main(string[] args) { // create the object DataCache cache = new DataCache();   // create the delegate CacheFlusher flusher = new CacheFlusher(cache.FlushToDisk);   // call the delegate asynchronously flusher.BeginInvoke("data.dat", new AsyncCallback(CallbackMethod), flusher);   // wait to exitConsole.WriteLine("Press enter to exit"); Console.ReadLine(); }   staticvoid CallbackMethod(IAsyncResult result) { // get the delegate that was used to call that// method CacheFlusher flusher = (CacheFlusher) result.AsyncState;   // get the return value from that method callint returnValue = flusher.EndInvoke(result);   Console.WriteLine("The result was " + returnValue); }

    Tenta fazer parecido com o código acima, ai toda vez que terminar a executação do BeginInvoke ele vai retornar o valor para

    metodo CallbackMethod, neste metodo vc seta o retorno.

    quarta-feira, 4 de setembro de 2013 17:07