XAML Net Maui中的活动指示器问题

wb1gzix0  于 2023-09-28  发布在  其他
关注(0)|答案(2)|浏览(88)

我有一个活动指示器控件,我需要在按下按钮时显示它。这个按钮可以在屏幕上显示一二。问题是活动指示器是在完成数据收集过程后显示的,而不是在开始时显示的。我的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>

C#代码是:

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

有什么办法解决这个问题吗?谢谢!

a64a0gku

a64a0gku1#

看起来你缺少了ObtenerPrevision方法的codec/await。
你可以试试这样

public async void ObtenerPrevision()
{
    await Task.Delay(10000);
    acIndicator.IsVisible = false;
    acIndicator.IsRunning = false;
}
bpsygsoo

bpsygsoo2#

我建议使用ViewModel和MVVM toolkit以及DataBinding。它看起来与此类似,您需要将ViewModel和Page注册为服务,以及MauiProgram CreateMauiApp()类中的HttpClient:

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文件中设置viewmodel作为您的数据类型,如下所示:

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

你也可以通过DataBindings填充你的TreeViewNodes,如下所示:

[ObservableProperty]
ObservableCollection<TreeViewNode> treeViews;

然后在xaml页面中使用ItemsSource="{Binding TreeViews}"进行数据绑定

相关问题