Проблема с индикатором активности в Net Maui

У меня есть элемент управления «Индикатор активности», который мне нужно отображать при нажатии кнопки. Эта кнопка позволяет отображать один два на экране. Проблема в том, что индикатор активности отображается после завершения процесса сбора данных, а не тогда, когда он начинается. Мой код xaml:

      <VerticalStackLayout>
        <ActivityIndicator x:Name="acIndicator"
                           IsVisible="False"
                           IsRunning="False"
                           Color="Red"/>
        <Button x:Name="btIndicatorOn"
                Text="Obtener Prevision"
                Clicked="btIndicatorOn_Clicked"/>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <mapas:Map x:Name="mapa"
                    IsVisible="false"
                    Grid.Row="0"
                    Grid.Column="0"/>  
            <ScrollView x:Name="scrollView"
                    Grid.Row="0"
                    Grid.Column="1"
                    VerticalOptions="FillAndExpand">
                <StackLayout>
                    <treeView:TreeView x:Name="tvPrevision">

                    </treeView:TreeView>
                </StackLayout>
            </ScrollView>
        </Grid>
    </VerticalStackLayout>

Мой код С#:

      void btIndicatorOn_Clicked(System.Object sender, System.EventArgs e)
    {
        acIndicator.IsVisible = true;
        acIndicator.IsRunning = true;
        // here I need to show the ActivityIndicator
        // mostrar mapa
        mapa.IsVisible = true;
        mapa.MoveToRegion(MapSpan.FromCenterAndRadius(new Location(41.21301, 1.73250), Distance.FromMiles(0.5)));
        string cadenaSituacion =  " 41.21º  N  1.73º  E" ;
        var pin = new Pin
        {
            Label = cadenaSituacion,
            Address = cadenaSituacion,
            Type = PinType.Place,
            Location = new Location(41.21301, 1.73250)
        };

        mapa.Pins.Add(pin);
        ObtenerPrevision();
    }
    
    public void ObtenerPrevision()
    {
        string url = string.Format("http://api.openweathermap.org/data/2.5/forecast?units=metric&lat={0}&lon={1}&lang=es&APPID={2}", viewModel.LatitudMapa, viewModel.LongitudMapa, OpenWeatherKey);
        WebClient web = new WebClient();

        var json = web.DownloadString(url);
        var Object = JsonConvert.DeserializeObject<weatherForecast>(json);
        weatherForecast forecast = Object;
        // Cargamos los datos en el tipo de dato definido
        List<list> filaMeteo = forecast.list;
        foreach (var item in filaMeteo)
        {
            DatosPrevision.Add(new TreeViewNode(item.dt_txt)
            {
                Children =
            {
                new TreeViewNode(item.weather[0].description),
                new TreeViewNode("Temperatura "+ String.Format("{0:N1}", item.main.temp) + " ºC"),
                new TreeViewNode("Dirección Viento "+ String.Format("{0:N1}", item.wind.deg) + " º"),
                new TreeViewNode("Velocidad Viento "+String.Format("{0:N1}", ((item.wind.speed * 3600) / 1852)) + " " + "Nudos"),
                new TreeViewNode("Presión atmosférica sobre el suelo "+item.main.grnd_level+ " hPa"),
                new TreeViewNode("Presión atmosférica sobre el mar "+item.main.sea_level+ " hPa"),
                new TreeViewNode("Humedad "+item.main.humidity+ "%"),
            }
            });

        }
        tvPrevision.ItemsSource = DatosPrevision;
        //acIndicator.IsVisible = false;
        //acIndicator.IsRunning = false;
    }

Есть идеи по решению этой проблемы? Спасибо !!!

1 ответ

Я бы рекомендовал использовать ViewModel с набором инструментов MVVM и DataBinding. Это будет выглядеть примерно так, и вам нужно будет зарегистрировать вашу ViewModel и страницу как службу, а также HttpClient внутри класса MauiProgram CreateMauiApp():

          builder.Services.AddTransient<HttpClient>();
    builder.Services.AddTransient<YourPageViewModel>();
    builder.Services.AddTransient<YourPage>();


public abstract partial class BaseViewModel : ObservableObject
{
    public BaseViewModel()
    {
    }

    [ObservableProperty]
    public bool isBusy = false;
}

public partial class YourPageViewModel : BaseViewModel
{
    private readonly HttpClient _httpClient;
    public YourPageViewModel(HttpClient httpClient)
    {
    }

    [RelayCommand]
    public async Task DownloadData()
    {
        IsBusy = true;
        try
        {
            var res = await _httpClient.GetAsync("http://api.openweathermap.org/data/2.5/forecast?units=metric&lat={0}&lon={1}&lang=es&APPID={2}", viewModel.LatitudMapa, viewModel.LongitudMapa, OpenWeatherKey);
            res.EnsureSuccessStatusCode();

            var obj = await res.Content.ReadFromJsonAsync<weatherForecast>().ConfigureAwait(true);
            // rest of your handling
        }
        finally
        {
             IsBusy = false;
        }

    }
}

в конструкторе YourPage:

          public YourPage(YourPageViewModel vm) 
    {
        InitializeComponent();
        //_vm = vm;
        this.BindingContext = vm;
    }
    //internal YourPageViewModel _vm; // if you need it here too

затем вы можете привязать команду, созданную с помощью «[RelayCommand]», и привязать ее к своей кнопке следующим образом:

          <Button x:Name="btIndicatorOn"
            Text="Obtener Prevision" Command="{Binding DownloadDataCommand}"/>

    <ActivityIndicator x:Name="acIndicator"
                       IsVisible="{Binding IsBusy}"
                       IsRunning="{Binding IsBusy}"
                       Color="Red"/>

чтобы получить intellisense и повысить производительность, также установите модель представления в качестве типа данных в файле xaml страницы, например:

      <Page ....
           xmlns:viewmodels="clr-namespace:{YOURNAMESPACE}.ViewModels"
           x:DataType="viewmodels:YourPageViewModel" >

вы также можете заполнить свои TreeViewNodes через DataBindings следующим образом:

      [ObservableProperty]
ObservableCollection<TreeViewNode> treeViews;

а затем используйте привязку данных на своей странице xaml с помощьюItemsSource="{Binding TreeViews}"

Другие вопросы по тегам