Esse não é o primeiro artigo sobre como salvar e recuperar imagens em um banco de dados SQL Server, mas ele tem algumas diferenças dos artigos anteriores. Neste artigo, vou criar uma aplicação WPF com um menu de opções onde o usuário poderá carregar um formulário Wpf para salvar e outro para recuperar imagens.
Então, neste projeto iremos usar 3 Windows (arquivos .xaml). Você não deve confundir Page com Windows em uma aplicação WPF.
As páginas WPF podem ser usadas para aplicativos de navegador XAML, você também pode carregá-las em seu próprio aplicativo usando o controle Frame, ou você pode usar um NavigationWindow e criar o equivalente a um navegador como aplicativo. Assim, uma Page não é independente e geralmente é visualizada em um container.
As janelas WPF são janelas normais WPF, que podem hospedar páginas usando um frame. As janelas podem ser exibidas de forma independente.
Recursos usados:
Definindo o modelo dados
Para armazenar as imagens vamos definir o banco de dados Cadastro.mdf e a tabela Imagens com a estrutura mostrada a seguir:
Criando o projeto no Visual Studio 2013 Express Windows desktop
Abra o VS 2013 Express for Windows desktop e clique em New Project. Selecione a linguagem Visual Basic ou e o template WPF Application e informe o nome Wpf_GerenciaImagens, clicando em seguida no botão OK:
Será criado o projeto WPF contendo uma janela MainWindow.xaml, que será a nossa janela principal.
Vamos incluir mais duas janelas no projeto: uma para salvar imagens e outra para recuperar imagens.
No menu PROJECT, clique em Add New Item e a seguir selecione o template WPF -> Window(WPF). Depois informe o nome SalvarImagem.xaml e clique no botão Add:
Repita o procedimento anterior e crie outra janela com o nome RecuperarImagem.xaml no projeto. Neste momento, nosso projeto será visualizado na janela Solution Explorer, exibindo a seguinte estrutura:
Vamos, agora, criar o menu da aplicação na janela MainWindow.xaml.
Criando o menu da aplicação
Vamos abrir o arquivo MainWindow.xaml e definir o código para criar um menu de opções. A criação é feita usando as classe Menu e MenuItem, que representam um menu e um item de menu, respectivamente.
Um Menu é uma coleção de itens de menu com um comando associado a cada um dos itens do menu. Um item de menu pode ter itens de menu filhos, chamado ‘submenus’.
Antes de definir o código, vamos criar uma pasta no projeto chamada Imagens, que irá armazenar as imagens que iremos usar.
No menu PROJECT, clique em New Folder e informe o nome Imagens. A seguir, clique com o botão direito do mouse sobre esta pasta e, a seguir, clique em Add ExistingItem e selecione as imagens.
Abaixo temos o código XAML, que define um menu Arquivos com 3 itens: Salvar Imagem, Recuperar Imagem e Sair:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Salvar e Recuperar Imagens - MENU" Height="600" Width="750" WindowStartupLocation="CenterScreen">
<Grid>
<DockPanel>
<Menu DockPanel.Dock="Top" Background="Aquamarine">
<MenuItem Header="_Arquivos" FontSize="16">
<MenuItem Header="_Salvar Imagem" Click="Salvar_Click">
<MenuItem.Icon>
<Image Source="Imagens/salvar.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Recuperar Imagem" Click="Recuperar_Click">
<MenuItem.Icon>
<Image Source="Imagens/recuperar.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Encerrar Programa" Click="Sair_Click">
<MenuItem.Icon>
<Image Source="Imagens/sair.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
</DockPanel>
</Grid>
</Window>
Note que estamos definindo na propriedade Image Source o caminho da imagem que estamos usando no menu. Observe também que a janela MainWindow será exibida centralizada: WindowStartupLocation=”CenterScreen”. O código também definir os eventos Click para cada item do menu.
A seguir, abra o arquivo MainWindow.xaml.vb e defina o código que irá abrir as janelas para Salvar e Recuperar as imagens:
Class MainWindow
Private Sub Salvar_Click(sender As Object, e As RoutedEventArgs)
Dim salvaImg As New SalvarImagem
salvaImg.Show()
End Sub
Private Sub Recuperar_Click(sender As Object, e As RoutedEventArgs)
Dim recupImg As New RecuperarImagem
recupImg.Show()
End Sub
Private Sub Sair_Click(sender As Object, e As RoutedEventArgs)
If MessageBox.Show("Deseja realmente encerrar o programa ?", "Confirma", MessageBoxButton.YesNo) = MessageBoxResult.Yes Then
Application.Current.Shutdown()
End If
End Sub
End Class
Assim, quando o usuário clicar em um item do menu, o evento Click irá acionar o respectivo código definido acima.
Implementando as funcionalidades para salvar imagens
Abra o projeto criado e, a seguir, abra o arquivo SalvarImagem.xaml e inclua os seguintes controles a partir da ToolBox:
- TextBox = Name=txtArquivo
- Button = btnProcurar
- Button = btnSalvar
- Button = btnSair
- Image = imgArquivo
- Label = lblmsg
Defina os controles conforme o leiaute da figura abaixo:
O código XAML gerado é visto abaixo:
<Window x:Class="SalvarImagem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Salvar Imagens" Height="500" Width="600" WindowStartupLocation="CenterScreen">
<Grid Background="Aqua">
<TextBox x:Name="txtArquivo" HorizontalAlignment="Left" Height="23" Margin="51,374,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="432"/>
<Button x:Name="btnProcurar" Content="Procurar" HorizontalAlignment="Left" Margin="488,374,0,0" VerticalAlignment="Top" Width="75" Background="#FF9A9AC1" Click="btnProcurar_Click"/>
<Button x:Name="btnSalvar" Content="Salvar a imagem no Banco de dados" HorizontalAlignment="Left" Margin="51,402,0,0" VerticalAlignment="Top" Width="432" Background="#FF9898CF" Click="btnSalvar_Click"/>
<Button x:Name="btnSair" Content="Sair" HorizontalAlignment="Left" Margin="488,402,0,0" VerticalAlignment="Top" Width="75" Background="#FFAEAED6" Click="btnSair_Click"/>
<Image x:Name="imgArquivo" HorizontalAlignment="Left" Height="309" Margin="51,29,0,0" VerticalAlignment="Top" Width="432" ToolTip="Selecione a imagem para Salvar" />
<Label x:Name="lblmsg" Content="" HorizontalAlignment="Left" Margin="51,429,0,0" VerticalAlignment="Top" Width="432" Height="30"/>
</Grid>
</Window>
Observe que a janela SalvarImagem será exibida centralizada: WindowStartupLocation=”CenterScreen” e que definimos os eventos Click para cada controle Button.
Vamos declarar os seguintes namespaces que iremos usar nesta janela:
- Imports Microsoft.Win32
- Imports System.IO
- Imports System.Data.SqlClient
- Imports System.Data
Agora vamos definir o código em cada um dos eventos Click.
1. Código do evento Click do botão Procurar:
Private Sub btnProcurar_Click(sender As Object, e As RoutedEventArgs)
lblmsg.Content = ""
imgArquivo.Source = Nothing
Dim FileDialog As New OpenFileDialog
Try
FileDialog.Title = "Selecione um Arquivo"
FileDialog.InitialDirectory = ""
FileDialog.Filter = "Image Files (*.gif,*.jpg,*.jpeg,*.bmp,*.png)|*.gif;*.jpg;*.jpeg;*.bmp;*.png"
FileDialog.FilterIndex = 1
FileDialog.ShowDialog()
txtArquivo.Text = FileDialog.FileName()
lblmsg.Content = NomeArquivo(txtArquivo.Text.Trim)
Dim bmp As New BitmapImage(New Uri(txtArquivo.Text.Trim))
If bmp.Width < 484 And bmp.Height < 268 Then
imgArquivo.Stretch = Stretch.None
imgArquivo.VerticalAlignment = Windows.VerticalAlignment.Center
imgArquivo.HorizontalAlignment = Windows.HorizontalAlignment.Center
imgArquivo.Source = bmp
Else
imgArquivo.Stretch = Stretch.Uniform
imgArquivo.VerticalAlignment = Windows.VerticalAlignment.Center
imgArquivo.HorizontalAlignment = Windows.HorizontalAlignment.Center
imgArquivo.Source = bmp
End If
Catch ex As Exception
lblmsg.Content = "Você não selecionou nenhum arquivo Imagem..."
End Try
End Sub
Este código abre uma caixa de diálogo que permite selecionar uma imagem, exibindo-a a seguir no controle PictureBox – imgArquivo – do formulário:
O código utiliza o método NomeArquivo(), cujo objetivo é apenas extrair o home do arquivo do caminho completo de sua localização:
Private Function NomeArquivo(ByVal Pth As String) As String
Dim posicaoBarra As Integer = Pth.LastIndexOf("\")
Dim _nomeArquivo As String = Pth.Substring(posicaoBarra + 1)
Return _nomeArquivo
End Function
Após selecionar a imagem, o usuário clica no botão ‘Salvar a imagem no banco de dados” para armazenar a imagem na tabela Imagens:
Private Sub btnSalvar_Click(sender As Object, e As RoutedEventArgs)
Try
lblmsg.Content = ""
Dim Stream As FileStream
Dim Reader As StreamReader
Stream = New FileStream(txtArquivo.Text, FileMode.Open, FileAccess.Read)
Reader = New StreamReader(Stream)
Dim ImgData(Stream.Length - 1) As Byte
Stream.Read(ImgData, 0, Stream.Length - 1)
Dim str As String = "Data Source=.\SQLEXPRESS;Initial Catalog=Cadastro;Integrated Security=True"
Dim con As New SqlConnection(str)
Dim sql As String = "INSERT INTO Imagens (imagemNome, Imagem) VALUES(@ImagemNome, @Imagem)"
Dim cmd As New SqlCommand(sql, con)
cmd.Parameters.Add("@ImagemNome", SqlDbType.Text).Value = NomeArquivo(txtArquivo.Text.Trim)
cmd.Parameters.Add("@Imagem", SqlDbType.Binary, Stream.Length).Value = ImgData
con.Open()
cmd.ExecuteNonQuery()
lblmsg.Content = " O arquivo " & NomeArquivo(txtArquivo.Text.Trim) & " foi armazenado com sucesso...."
con.Close()
Catch ex As Exception
lblmsg.Content = ex.Message
End Try
End Sub
O código acima abre o arquivo criando um stream e, a seguir, um array de bytes.
A seguir , usando ADO .NET, definimos a string de conexão com o banco de dados e a instrução SQL INSERT INTO para incluir os dados na tabela.
Atribuímos os parâmetros para o objeto parameters, e usamos o método ExecuteNonQuery() para executar a instrução SQL.
Implementando as funcionalidades para recuperar e exibir as imagens salvas
Abra o projeto e, a seguir, abra o arquivo RecuperarImagem.xaml e inclua os seguintes controles a partir da ToolBox:
- ListBox = Name=lstbImagens
- Imagem = imgDados
- Button = btnSair
Defina os controles conforme o leiaute da figura abaixo:
O código XAML gerado é visto abaixo:
<Window x:Class="RecuperarImagem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Recuperar Imagens" Height="500" Width="680" WindowStartupLocation="CenterScreen">
<Grid Background="LightGreen">
<ListBox x:Name="lstbImagens" HorizontalAlignment="Left" Height="385" Margin="10,44,0,0" VerticalAlignment="Top" Width="215"/>
<Image x:Name="imgDados" HorizontalAlignment="Left" Height="386" Margin="247,43,0,0" VerticalAlignment="Top" Width="415"/>
<Button x:Name="btnSair" Content="Sair" HorizontalAlignment="Left" Margin="150,434,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.32,1.3" Click="btnSair_Click"/>
</Grid>
</Window>
Observe que a janela RecuperarImagem será exibida centralizada: WindowStartupLocation=”CenterScreen” e que definimos o evento Click para o controle Button – btnSair.
Vamos declarar os seguintes namespaces que iremos usar nesta janela:
- Imports Microsoft.Win32
- Imports System.IO
- Imports System.Data.SqlClient
- Imports System.Data
Logo após a declaração da janela, vamos definir uma variável con, do tipo SqlConnection, que será usada no projeto:
Dim con As SqlConnection = Nothing
Agora vamos definir o código no evento Window_Loaded da janela RecuperarImagem que ocorre quando a janela é carregada:
Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
Try
con = New SqlConnection("Data Source=.\SQLEXPRESS;Initial Catalog=Cadastro;Integrated Security=True")
con.Open()
Dim dad As SqlDataAdapter = New SqlDataAdapter("Select imagemId, imagemNome from Imagens", con)
Dim dst As New DataSet
dad.Fill(dst, "ImgContainer")
Dim datarow As DataRow
For Each datarow In dst.Tables(0).Rows
Dim lbitem As New ListBoxItem
lbitem.Content = datarow(1).ToString
lbitem.DataContext = datarow(0).ToString
lstbImagens.Items.Add(lbitem)
Next
Catch ex As Exception
MessageBox.Show(" Erro : " & ex.Message)
Finally
con.Close()
End Try
End Sub
Este código acessa o banco de dados Cadastro e executa uma instrução SQL – Select imagemId, imagemNome from Imagens – para recuperar as imagens armazenadas na tabela Imagens.
A seguir, criamos um dataset e exibimos o nome da imagem recuperada no controle ListBox – lstbImagens.
Nosso objetivo é permitir que o usuário selecione uma imagem no controle ListBox e a mesma seja exibida no controle Image.
Para isso, vamos definir o código abaixo no evento SelectionChanged do controle ListBox:
Private Sub lstbImagens_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles lstbImagens.SelectionChanged
ExibirImagem()
End Sub
Neste código, cada item selecionado no controle ListBox irá chamar a rotina ExibirImagem() cujo código mostramos a seguir:
Private Sub ExibirImagem()
Try
con = New SqlConnection("Data Source=.\SQLEXPRESS;Initial Catalog=Cadastro;Integrated Security=True")
Dim lbitem As ListBoxItem = TryCast(lstbImagens.SelectedItem, ListBoxItem)
Dim dst As New DataSet
con.Open()
Dim dad As New SqlDataAdapter("Select Imagem from Imagens where imagemId='" + lbitem.DataContext.ToString + "'", con)
dad.Fill(dst, "ImgContainer")
Dim ImgSource() As Byte = DirectCast(dst.Tables(0).Rows(0)(0), Byte())
Dim stream As MemoryStream = New MemoryStream()
stream.Write(ImgSource, 0, ImgSource.Length - 1)
stream.Seek(0, SeekOrigin.Begin)
Dim bitmap As New BitmapImage
bitmap.BeginInit()
bitmap.StreamSource = stream
bitmap.EndInit()
If bitmap.Width < 390 Or bitmap.Height < 340 Then
imgDados.Stretch = Stretch.None
imgDados.VerticalAlignment = Windows.VerticalAlignment.Center
imgDados.HorizontalAlignment = Windows.HorizontalAlignment.Center
imgDados.Source = bitmap
Else
imgDados.Stretch = Stretch.Uniform
imgDados.VerticalAlignment = Windows.VerticalAlignment.Center
imgDados.HorizontalAlignment = Windows.HorizontalAlignment.Center
imgDados.Source = bitmap
End If
Catch ex As Exception
MessageBox.Show(" Erro : " & ex.Message)
Finally
con.Close()
End Try
End Sub
O código obtém o id da imagem selecionada e localiza a imagem na tabela imagem.
A seguir, cria um stream com os dados da imagem e o atribui a um objeto do tipo BitmapImage para, em seguida, atribuir os dados ao controle Image e exibir a imagem selecionada:
Pegue o projeto completo aqui: Wpf_GerenciaImagens.zip














