Проблема с индикатором активности в 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}"