MVVM Starter Pack – Iniciando no MVVM – C#

Introdução

Fala pessoal, tudo bom?

Nesse post irei falar um pouco sobre o padrão de projetos chamado MVVM (Model – View – ViewModel) usado principalmente em aplicações XAML (WPF, UWP, Xamarin e etc).

Saliento, que a intenção aqui não é desenvolver um curso, ou um material completo sobre o assunto. Existem inúmeras fontes sobre. Se trata de um manual básico para a implementação desse padrão para pessoas que já possuem um conhecimento, ainda que básico, sobre o XAML e programação em geral.

Embora o projeto de exemplo que iremos desenvolver e eu disponibilizarei ao final tenha sido escrito para o WPF (Windows Presentation Foundation), os conceitos, classes e técnicas que abordarei neste post são como se fossem um Starter Pack para o MVVM. Independente de quem seja você ou qual seja o segmento do sistema/software/aplicativo ou plataforma (WPF, UWP, Xamaring…) que você pretende desenvolver usando MVVM, você irá, com toda certeza, usar a grande maioria do conteúdo que vou apresentar.

Então, fique tranquilo and here we go!

Conceitos

Para começar, vamos tentar entender o porquê de implementar um padrão de projeto.

(mais…)

Anúncios

.NET CORE: API para conversão de moedas – Yahoo Currency

Yahoo Currency

Salve galera. Na verdade, eu já havia feito uma postagem sobre isso no passado. Mas decidi reescrever algumas partes do código e atualizar o projeto (de Portable Class Library) para uma Class Library(.NET CORE 2) que é multi plataforma.

O funcionamento é o mesmo, a diferença principal fica pelo suporte à assincronicidade permitindo que você use métodos async e use await.

Esse é mais um projeto livre e open source que estou disponibilizando no meu GITHUB.

Os códigos estão sumarizados(documentados) e acompanham um Demo em WPF.

Abaixo uma pequena porção de código:

        ///

        /// O código abaixo é um exemplo simples de como usar os webservices de moeda de forma assíncrona
        /// 

        /// 
        public static async Task AsyncExample()
        {
            HL.YahooCurrency.Currency currency = new HL.YahooCurrency.Currency();

            //VOCÊ DEVE INCLUIR A LINHA ABAIXO OBRIGATORIAMENTE
            //É de extrema importância que você use o método WaitLoad() para aguardar a inicialização desse objeto, que ocorre de forma assíncrona
            await currency.WaitLoad();

            //Seleciona a moeda de origem
            currency.SourceUnit = currency.Units.ElementAt(0);
            //Seleciona a moeda de destino, para a qual se quer converter um valor
            currency.OutputUnit = currency.Units.ElementAt(1);
            //Dá um valor para conversão
            currency.SourceValue = 2.32f;
            //Mostra o valor convertido para a moeda de destino
            System.Diagnostics.Debug.WriteLine(currency.OutputValue);
        }

        ///

        /// O código abaixo é um exemplo simples de como usar os webservices de moeda de forma síncrona(normal)
        /// 

        public static void SynchronousExample()
        {
            HL.YahooCurrency.Currency currency = new HL.YahooCurrency.Currency();

            //VOCÊ DEVE INCLUIR A LINHA ABAIXO OBRIGATORIAMENTE
            //É de extrema importância que você use o método WaitLoad() para aguardar a inicialização desse objeto, que ocorre de forma assíncrona
            //Ao invés de usar await, você pode usar o método .Wait() em contextos síncronos.
            //Dessa forma, a thread em execução irá ser bloqueada por algumas frações de tempo, até que o carregamento dos dados seja feito completamente
            //Normalmente, isso deverá tomar cerca de 1 segundo, mas em conexões de internet mais lentas, pode levar até 6. Ou seja, a interface de usuário irá ficar bloqueada durante esse tempo
            currency.WaitLoad().Wait();

            //Seleciona a moeda de origem
            currency.SourceUnit = currency.Units.ElementAt(0);
            //Seleciona a moeda de destino, para a qual se quer converter um valor
            currency.OutputUnit = currency.Units.ElementAt(1);
            //Dá um valor para conversão
            currency.SourceValue = 2.32f;
            //Mostra o valor convertido para a moeda de destino
            System.Diagnostics.Debug.WriteLine(currency.OutputValue);
        }

Gostou?

Detalhe, esse objeto YahooCurrency pode ser usado diretamente no XAML, pois ele implementa a interface INotifyPropertyChanged, permitindo que seja feito Data Bindings. Quando usando em XAML ele irá operar, por padrão, de forma assíncrona. Você deverá utilizar a propriedade IsLoading para exibir alguma mensagem de carregamento para o usuário (enquanto os dados são baixados) e/ou desabilitar os controles da interface.

Isso tudo que mencionei acima está implementado no exemplo em WPF que acompanha a API.

Chega de papo, aí está o link:

GitHub – HerbertLausmann/HL.YahooCurrency: .NET C# Multiplatform wrapper for Yahoo Currency Web Service. Convert between over 100 different currencies.

Lembrando, que como ela é escrita sob os padrões do .NET STANDARD 2, você poderá usa-la no Xamarin, Mono e etc.

Um abraço!

.NET CORE: API de previsão do tempo – Yahoo Weather

Surprise modafocas!

Queridos colegas, amigos, parceiros, compatriotas, conterrâneos, irmãos!

Nesse post venho apresentar-vos a minha API (escrita em C#/.NET CORE2) para previsão do tempo.

Ela é, basicamente, uma ponte em C# para o WebService de clima do Yahoo. Com ela você consegue obter muitas informações sobre o clima numa dada região, como por exemplo:

  1. Horário do nascer e pôr do sol
  2. Umidade e pressão atmosférica
  3. A sensação térmica, direção e velocidade do vento
  4. As temperaturas máxima e mínima previstas para a previsão
  5. Previsão do dia atual e dos 9 dias à frente

O webservice do yahoo, originalmente, retorna apenas os resultados em inglês. Mas eu adicionei suporte à globalização e assim ela emite os textos da previsão (Ex: Parcialmente Nublado, Chuvoso) em português.

Vale destacar que, sendo uma api escrita para o .NET CORE, ela pode ser usada em múltiplas plataformas, incluindo o XAMARIN e o MONO.

Ela também implementa a interface INotifyPropertyChanged podendo ser usada tanto em código (C#/VB.NET, whatever) quanto no XAML com Data Binding.

Saliento, também, que implementei suporte assíncrono. Você pode fazer umas coisinhas assim:

            YahooWeather weather = await YahooWeather.LoadAsync("New York city");
            Console.WriteLine(weather.Condition.Text);

Bacana né?

Isso tudo disponibilizado gratuitamente e com código aberto no GITHUB:

GitHub – HerbertLausmann/HL.YahooWeather: A .NET C# Multiplatform wrapper for the Yahoo Weather API

Divirta-se!
That’s all folks!

Criando um ícone personalizado para seu Aplicativo Windows – DICA

Icon Pro

Criando um ícone a partir de um arquivo SVG

GitHub – HerbertLausmann/HL.IconPro

Fala galera, beleza?!

Neste post eu venho lhes (re)apresentar minha ferramenta open source para criação de ícones para o Windows.

Como vocês podem ver acima, no GIF, é bem simples!! Basta selecionar uma imagem (PNG ou SVG), selecionar os tamanhos que irão para dentro do ícone, e pronto! Só salvar!

(mais…)

.NET: Medir força de senhas – C#

Password Strength.gif

Visualizando em tempo real a força da senha

Salve internautas! Tudo tranquilo?!

Então, depois de quase um ano após a última postagem, eis que eu retorno da cinzas, e mais zika dos códigos ainda haha! Aproveitando que entrei de férias (permanentes) agora posso me dedicar a uma coisa que gosto muito: Programação!

E nada melhor que elaborar uma postagem didática e útil, pois eu amo compartilhar conhecimento!

Chega de papo, and let’s go!

Já precisou alguma vez medir a força de uma senha? Bom, eu nunca, mas como precisava de um passatempo, resolvi estudar uma maneira de como fazer isso.

(mais…)

Windows Explorer: Abrir Explorer com arquivo/pasta selecionado – C#

Falaí galera!!!

Fiquei um tempinho sem postar.. Tá ok, um tempão!

Mas eu não ia deixar o blog fazer aniversário de inatividade, então resolvi postar alguma coisa..

O assunto de hoje é o Windows Explorer. Vou mostrar como abrir o Windows Explorer selecionando algum arquivo ou pasta. Um exemplo de uso muito bom é um gerenciador de downloads que muitos já devem ter experimentado. Quando termina o download, normalmente ele lhe dá a opção de Abrir Pasta, que vai abrir a pasta onde está o arquivo que você baixou. E, de quebra, ele seleciona o arquivo para facilitar a localização do mesmo pelo usuário final.

Executar essa tarefa em código é bem simples. Eis um exemplo:

        public void OpenAndSelectPath(string path)
        {
            bool isfile = System.IO.File.Exists(path);
            if (isfile)
            {
                string argument = @"/select, " + path;
                System.Diagnostics.Process.Start("explorer.exe", argument);
            }
            else
            {
                bool isfolder = System.IO.Directory.Exists(path);
                if(isfolder)
                {
                    string argument = @"/select, " + path;
                    System.Diagnostics.Process.Start("explorer.exe", argument);
                }
            }
        }

Essas poucas linhas acima farão este trabalho. Basicamente, o que fazemos é rodar o processo explorer.exe (Corresponder ao Windows Explorer) informando como argumento a instrução -select e o caminho do arquivo/pasta a ser selecionado. Segue um breve exemplo de uso:

       OpenAndSelectPath(@"H:\Biblioteca\Documentos\arquivo.txt");

Simples e prático! 🙂

Espero voltar em breve com novos posts!

.Net: Classe para pesquisa de arquivos assíncrona e com múltiplos filtros – C#

Olá Pessoal,

Esse é o meu último dia de férias do trabalho (choro eterno), e acabei escrevendo um código para uma contribuição no MSDN que achei que seria interessante publicar.

É uma classe para pesquisa de arquivos assíncrona e que permite o uso de múltiplos filtros (de forma simultânea, na qual só serão retornados os resultados que satisfizerem a todos os filtros, de forma normal, onde serão retornados os arquivos que atendem a qualquer um dos filtros, mesmo que só um).

É um código simples, mas que na pressa, vale um Ctrl + C Ctrl + V. Enfim, segue o código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace HL.IO
{
    public class FileSearch
    {
        private string[] _Filters;
        public string[] Filters
        {
            get { return _Filters; }
            set { _Filters = value; }
        }

        private SearchOptions _SearchOption;
        public SearchOptions SearchOption
        {
            get { return _SearchOption; }
            set { _SearchOption = value; }
        }

        public FileSearch(SearchOptions SearchOption, params string[] Filters)
        {
            _Filters = Filters;
            _SearchOption = SearchOption;
        }
        public FileSearch()
        {
            _SearchOption = SearchOptions.AllDirectories | SearchOptions.MatchAllFilters;
            _Filters = null;
        }
        public IEnumerable<string> Search(string RootFolder)
        {
            if (_SearchOption.HasFlag(SearchOptions.AllDirectories))
            {
                IEnumerable<string> result = Directory.EnumerateFiles(RootFolder, "*.*", System.IO.SearchOption.AllDirectories);
                if (_SearchOption.HasFlag(SearchOptions.MatchAllFilters))
                    return result.Where(s => Path.GetFileName(s).ContainsAll(_Filters,
                        _SearchOption.HasFlag(SearchOptions.CaseSensitive)));
                else
                    return result.Where(s => Path.GetFileName(s).ContainsAny(_Filters,
                        _SearchOption.HasFlag(SearchOptions.CaseSensitive)));
            }
            else
            {
                IEnumerable<string> result = Directory.EnumerateFiles(RootFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly);
                if (_SearchOption.HasFlag(SearchOptions.MatchAllFilters))
                    return result.Where(s => Path.GetFileName(s).ContainsAll(_Filters,
                        _SearchOption.HasFlag(SearchOptions.CaseSensitive)));
                else
                    return result.Where(s => Path.GetFileName(s).ContainsAny(_Filters,
                        _SearchOption.HasFlag(SearchOptions.CaseSensitive)));
            }
        }

        #region Async
        public void AsyncSearch(string RootFolder)
        {
            SynchronizationContext context = SynchronizationContext.Current;
            if (context == null)
            {
                context = new System.Threading.SynchronizationContext();
            }
            Thread th = new Thread(new ThreadStart(() =>
            {
                IEnumerable<string> result = Search(RootFolder);
                context.Send(new SendOrPostCallback((object state) =>
                {
                    OnAsyncSearchCompleted((IEnumerable<string>)state);
                }), result);
            }));
            th.IsBackground = false;
            th.SetApartmentState(ApartmentState.STA);
            th.Start();
        }
        public event AsyncSearchCompletedEventHandler AsyncSearchCompleted;
        protected virtual void OnAsyncSearchCompleted(IEnumerable<string> Result)
        {
            if (AsyncSearchCompleted != null)
            {
                AsyncSearchCompleted(this, new AsyncSearchCompletedEventArgs(Result));
            }
        }
        #endregion
    }

    public delegate void AsyncSearchCompletedEventHandler(object sender, AsyncSearchCompletedEventArgs e);

    public class AsyncSearchCompletedEventArgs
    {
        private IEnumerable<string> _result;
        public IEnumerable<string> Result
        {
            get { return _result; }
        }
        public AsyncSearchCompletedEventArgs(IEnumerable<string> Result)
        {
            _result = Result;
        }
    }
    public enum SearchOptions : int
    {
        /// <summary>
        /// The search engine will seach only on top level of the given root folder.
        /// </summary>
        TopDirectoryOnly = 1,
        /// <summary>
        /// The search engine will search in all the directory tree starting from the given root folder
        /// </summary>
        AllDirectories = 2,
        /// <summary>
        /// The search engine will use case sensitive approach.
        /// </summary>
        CaseSensitive = 4,
        /// <summary>
        /// If set, the search engine will return only the results matching all the filters.
        /// </summary>
        MatchAllFilters = 8
    };
    public static class StringExtensions
    {
        public static bool ContainsAll(this string Source, string[] strs, bool CaseSensitive)
        {
            foreach (string str in strs)
            {
                if (CaseSensitive)
                {
                    if (!Source.Contains(str)) return false;
                }
                else
                {
                    if (!Source.ToLower().Contains(str.ToLower())) return false;
                }
            }
            return true;
        }

        public static bool ContainsAny(this string Source, string[] strs, bool CaseSensitive)
        {
            foreach (string str in strs)
            {
                if (CaseSensitive)
                {
                    if (Source.Contains(str)) return true;
                }
                else
                {
                    if (Source.ToLower().Contains(str.ToLower())) return true;
                }
            }
            return false;
        }
    }
}

Mostrarei também um pequeno exemplo:

        private void btnSearch_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.ShowDialog();
            FileSearch searcher = new FileSearch(SearchOptions.AllDirectories, ".png", ".bmp", ".jpeg");
            searcher.AsyncSearchCompleted += searcher_AsyncSearchCompleted;
            searcher.AsyncSearch(dialog.SelectedPath);
        }

        private void searcher_AsyncSearchCompleted(object sender, AsyncSearchCompletedEventArgs e)
        {
            listBox1.Items.Clear();
            listBox1.Items.AddRange(e.Result.ToArray());
        }

No exemplo acima a classe FileSearch é usada para encontrar todos os arquivos PNG, BMP e JPEG da pasta informada. Isso é bem básico, mas dá para fazer bastante coisa. Incluir uma palavra chave que o nome do arquivo deve conter também é uma opção. E o melhor de tudo, assíncrono. Não irá congelar a interface de usuário enquanto realiza a busca.

That’s all folks!!!