Desenvolvimento - Silverlight
Usando Timer no WPF e Silverlight
Quem procurar por um controle Timer na toolbox do WPF ou Silverlight, como de costume em aplicações Windows Forms ou VB6, não irá encontrar.
por Gustavo MalheirosQuem procurar por um controle Timer na toolbox do WPF ou Silverlight, como de costume em aplicações Windows Forms ou VB6, não irá encontrar. O conceito de Timers é diferente, pois usa Multithreading, o que faz com que o uso seja muito cuidadoso. Se você tentar mudar uma propriedade de um objeto (elemento visual) da tela, vai receber um erro. Para evitar o trabalho tedioso de controlar as threads, você pode utilizar um tipo especial de Timer, chamado DispatcherTimer, que roda na Thread principal da aplicação, na interface do usuário. Assim você pode controlar objetos da tela de acordo com tempo configurado no Timer.
Como sempre, existem vantagens e desvantagens, porém a maior vantagem é o fato de rodar na thread principal. Um exemplo de cenário, seria a necessidade de periodicamente acessar um WebService para obter dados novos e atualizar uma grid ou gráfico na tela. Como desvantagem, pelo fato dele não usar Multithreading verdadeira, uma aplicação que precisa fazer pequenas tarefas em frações de segundo ou precisa ser mais responsiva com operações de alta latência, é aconselhável usar o System.Threading.Timer .
Vamos aqui fazer um pequeno exemplo de utilização:
Crie um projeto do tipo Silverlight Application no Visual Studio 2008.
Essa é a estrutura do projeto:
E este é nosso código XAML:
Aqui na MainPage.XAML foi criado um botão com uma ellipse que mudará de cor (vermelho ou verde), um TextBlock que mostra o estado da thread (Parado ou Processando) e um StackPanel onde será adicionado novos controles a cada segundo.
<UserControl x:Class="TimerSilverlight.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot">
<Button Height="32" x:Name="btnIniciar" Width="126" Click="btnIniciar_Click">
<StackPanel Orientation="Horizontal">
<Ellipse Fill="Red" Height="24" HorizontalAlignment="Left" Name="Ellipse1" Stroke="Black" Width="25" />
<TextBlock Text="Parado" Height="28" HorizontalAlignment="Right" Name="lblStatus"/>
</StackPanel>
</Button>
<StackPanel Width="300" x:Name="stackP" />
</Grid>
</UserControl>
Vamos para o code behind da página (MainPage.xaml.vb)
O DispatcherTimer fica no Namespace System.Windows.Threading.DispatcherTimer e aqui fazemos a declaração do Timer(dt) e uma variável (_threadRun) para controlar o processo.
Dim dt As New System.Windows.Threading.DispatcherTimer
Private _threadRun As Boolean = False
No Load da página adicionamos um delegate para o método processar. Em seguida definimos o intervalo (1 seg.) e damos inicio ao timer:
Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
AddHandler dt.Tick, AddressOf Processar
dt.Interval = New TimeSpan(0, 0, 1)
dt.Start()
End Sub
Na sub Processar, verificamos se a thread está rodando e atualizamos a Interface do usuário, mudando a cor do circulo para vermelho(Parado) ou verde (Processando), adicionando um novo TextBlock a cada segundo.
Private Sub Processar()
If _threadRun Then
Ellipse1.Fill = New SolidColorBrush(Colors.Green)
lblStatus.Text = "Processando"
Dim t As New TextBlock
t.Text = "Processando"
stackP.Children.Add(t)
Else
Ellipse1.Fill = New SolidColorBrush(Colors.Red)
lblStatus.Text = "Parado"
stackP.Children.Clear()
End If
End Sub
O botão apenas muda o estado da variável _threadRun:
Private Sub btnIniciar_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
If _threadRun Then
_threadRun = False
Else
_threadRun = True
End If
End Sub
O código completo da página fica assim:
Partial Public Class MainPage
Inherits UserControl
Dim dt As New System.Windows.Threading.DispatcherTimer
Private _threadRun As Boolean = False
Public Sub New()
InitializeComponent()
End Sub
Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
AddHandler dt.Tick, AddressOf Processar
dt.Interval = New TimeSpan(0, 0, 1)
dt.Start()
End Sub
Private Sub Processar()
If _threadRun Then
Ellipse1.Fill = New SolidColorBrush(Colors.Green)
lblStatus.Text = "Processando"
Dim t As New TextBlock
t.Text = "Processando"
stackP.Children.Add(t)
Else
Ellipse1.Fill = New SolidColorBrush(Colors.Red)
lblStatus.Text = "Parado"
stackP.Children.Clear()
End If
End Sub
Private Sub btnIniciar_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
If _threadRun Then
_threadRun = False
Else
_threadRun = True
End If
End Sub
End Class
Rode a aplicação (F5) e no browser, clicando no botão, devemos ter as seguintes situações:
Antes de clicar |
Depois de clicar |
Conclusão
Dessa forma conseguimos demonstrar o uso do Timer numa aplicação Silverlight. Lembrando que o mesmo serve para aplicações WPF.
Abraços e bons estudos!
- Acessando imagens externa (não compiladas) dentro do mesmo domínioSilverlight
- Trabalhando com enumeradosSilverlight
- Comunicação Local no SilverlightSilverlight
- Gerando Gráficos com Silverlight, WCF e LINQSilverlight
- Usando o Scroll do mouse para dar Zoom em Imagens com Silverlight 4Silverlight