En días de duda, en días de deliberación dolorosa.

En este artículo, quiero contarte cómo visualicé las estadísticas sobre la pandemia en curso y compartir qué características puedes cumplir usando Avalonia UI para esto.



Del autor
, . . — MIT .

Introducción


Este artículo asume que ya puede crear una aplicación simple usando AvaloniaUI. De lo contrario, consulte los tutoriales de AvaloniaUI o Habr .

Datos


En primer lugar, surgió la pregunta de dónde obtener los datos más recientes y una búsqueda rápida en Google encontró la siguiente API que cumplía con todos mis requisitos:

  1. Información general sobre el mundo.
  2. Información general para cada país.
  3. Historia de cada pais

Estructura de la aplicación


La aplicación consta de 3 pantallas diferentes.

Capturas de pantalla






Los movimientos entre las pantallas se construyen utilizando enrutamiento . Una característica interesante en este punto era la transferencia del disparador para la ruta a UserControl.

Para hacer esto, su ViewModel tuvo que aceptar Acción:

 public CountriesVM(IScreen screen, Action<Country> a)

 CurrentCountyCommand = 
            CountriesCommand = ReactiveCommand.CreateFromObservable(
                () => Router.Navigate.Execute(new CountriesVM(this,GoToCurrentCountry))
                );
....
  public void GoToCurrentCountry(Country c)
        {
            CurrentCountyCommand.Execute(c);
        }

Y la llamada a esta acción es seleccionar un elemento en la lista:

public Country SelectedCountry
        {
            get => _country;
            set
            {
                this.RaiseAndSetIfChanged(ref _country, value);
                A.Invoke(value);
            }
        }

Consultas


Para las llamadas a la API, se utilizó la biblioteca flurl. Que internamente usa HttpClient y Newtosoft, y en sí mismo es una extensión para cadenas.

Por lo tanto, la obtención de un modelo a partir de una solicitud se puede implementar en una línea:

 var allCases = await "https://corona.lmao.ninja/all".GetJsonAsync<AllCases>();

Imágenes


Para trabajar con la imagen usando flurl, obtuvimos una secuencia que debía empaquetarse en la secuencia de memoria para crear una instancia de mapa de bits:

private async Task<Bitmap> GetFlag(String flagUrl)
        {
            var flagStream = await flagUrl.GetStreamAsync();
            var memoryStream = new MemoryStream();
            flagStream.CopyTo(memoryStream);
            memoryStream.Position = 0;
            var bitmap = new Bitmap(memoryStream);
            return bitmap;
        }

Recolección y Filtrado


Se usaron datos dinámicos de ReactiveUI para mostrar la colección .

 SourceList<Country> countries = new SourceList<Country>();
 private ReadOnlyObservableCollection<Country> _collection;
 public ReadOnlyObservableCollection<Country> Collection => _collection;

countries.Connect().Filter(filter).ObserveOn(RxApp.MainThreadScheduler).Bind(out _collection).Subscribe();

También decidí agregar un filtro para buscar rápidamente un país por su nombre o abreviatura ISO3 .

Para hacer esto, la cadena de búsqueda estaba vinculada a la propiedad:


        public string FilterName
        {
            get => _filterName;
            set { this.RaiseAndSetIfChanged(ref _filterName, value); }
        }

Regla de filtro agregada:

        private Func<Country, bool> Filter(string filterName)
        {
            if (string.IsNullOrEmpty(filterName)) return x => true;
            return x => x.Name.ToUpper().Contains(filterName.ToUpper()) || x.ISO3.Contains(filterName.ToUpper());
        }

Y se crea el filtro en sí:

  var filter = this.WhenValueChanged(x => x.FilterName).Select(Filter);

Visualización gráfica


Para los gráficos, utilicé la biblioteca Oxyplot para AvaloniaUI.

Desafortunadamente, la versión está desactualizada en nuget o no la encontré, por lo que puede usar el paquete nuget que construí o arrastrar la fuente con github.

Para trabajar, debe agregar a App.xaml:

<StyleInclude Source="resm:OxyPlot.Avalonia.Themes.Default.xaml?assembly=OxyPlot.Avalonia"/>

Para mostrar un eje con una fecha específica, y no un número arbitrario (en el que el oxyplot convierte la fecha para el trabajo interno), debe especificar el tipo de eje en el marcado:

           <avalonia:Plot.Axes>
               <avalonia:DateTimeAxis StringFormat="yyyy-MM-dd" Position="Bottom"></avalonia:DateTimeAxis>
           </avalonia:Plot.Axes>

Fuentes y aplicaciones


Usando dotnet Publish, compilé binarios para las plataformas principales ( aquí ), pero para aquellos que estarán más interesados. El código fuente se puede encontrar en github .

En lugar de un epílogo


Esta aplicación se basa en una API de terceros, y espero que pronto esta API ya no sea compatible, porque no será necesario.

Lava tus bolígrafos y siéntate en casa. Y el soporte para Avalonia se puede encontrar aquí .

All Articles