在怀疑的日子里,在沉思的日子里

在本文中,我想告诉您我如何可视化正在进行的大流行的统计数据,并分享使用Avalonia UI可以实现的功能。



来自作者
, . . — MIT .

介绍


本文假定您已经可以使用AvaloniaUI创建一个简单的应用程序。如果没有,请查看AvaloniaUIHabr教程

数据


首先,出现了从哪里获取最新数据的问题,并且在Google中进行了快速搜索,发现以下满足我所有要求的api

  1. 有关世界的一般信息
  2. 每个国家的一般信息
  3. 每个国家的历史

应用结构


该应用程序包含3个不同的屏幕。

屏幕截图






屏幕之间的移动是使用工艺路线建立的这时一个有趣的功能是将触发器的路由转移到UserControl。

为此,其ViewModel必须接受Action:

 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);
        }

这个动作的调用是在列表中选择一个项目:

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

咨询处


对于api的调用,使用了flurl库。内部使用HttpClient和Newtosoft,本身是字符串的扩展。

因此,可以从一行中实现从请求获取模型:

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

图片


为了使用flurl处理图像,我们得到了一个流,该流需要打包到memorystream中以创建Bitmap实例:

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;
        }

收集和过滤


来自ReactiveUI的 Dinamic数据用于显示集合

 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();

我还决定添加一个过滤器,以按名称或ISO3缩写快速搜索国家/地区

为此,将搜索字符串绑定到该属性:


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

添加了过滤规则:

        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());
        }

然后创建过滤器本身:

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

图形显示


对于图形,我将Oxyplot库用于AvaloniaUI

不幸的是,该版本在nuget中已经过时,或者我找不到它,因此您可以使用我构建nuget包,或将其拖到github下。

要工作,您需要添加到App.xaml:

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

要显示具有特定日期而不是任意数字的轴(oxyplot将其转换为内部工作的日期),必须在标记中指定轴的类型:

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

来源和应用


使用dotnet publish,我为主要平台(在此处)以及对那些更感兴趣的人编译了二进制文件源代码可以在github上找到

而不是后记


该应用程序基于第三方api,我希望不久后将不再支持该api,因为将不再需要。

洗笔,坐在家里。这里可以找到对Avalonia的支持

All Articles