问题
I have listview. when the item is clicked, it will open a detail page to show detail information of selected item by taking selected item as a input parameter. To fetch the detail information I need to a REST api call. Once the response is received from api, I need to bind that information on the detail view/page.
listview.xaml.cs:
async void OnItemSelected(object sender, EventArgs args)
{
var layout = (BindableObject)sender;
var item = (Target)layout.BindingContext; // Passing to be used as input parameters value in API call.
await Navigation.PushAsync(new TargetDetailPage(new TargetDetailViewModel(item)));
}
TargetDetailPage.xaml:
<ContentPage.Content>
<RefreshView IsRefreshing="{Binding IsBusy, Mode=TwoWay}" Command="{Binding LoadTargetDetailCommand}">
<ScrollView>
<StackLayout BackgroundColor="#f8f9fa" Orientation="Vertical" >
<Label Text="{Binding Title}" x:Name="lblTitle" Padding="5,0,0,5" HorizontalOptions="StartAndExpand" FontAttributes="Bold" />
<Grid Padding="5" ColumnSpacing="0" RowSpacing="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0" BackgroundColor="#e9ecef" >
<Label Text="{Binding VerificationDetail.target_name, StringFormat='Use this phone number for {0}'}" HorizontalOptions="StartAndExpand" />
</StackLayout>
<StackLayout Grid.Row="0" Grid.Column="1" BackgroundColor="#e9efff" >
<Entry x:Name="txtNumber" Text="{Binding VerificationDetail.number}" ></Entry>
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="0" BackgroundColor="#e9ecef" >
<Label Text="Verification Cost" HorizontalOptions="StartAndExpand" />
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="1" BackgroundColor="#e9ecef" >
<Label Text ="{Binding VerificationDetail.cost}" HorizontalOptions="StartAndExpand" Margin="0"></Label>
</StackLayout>
<StackLayout Grid.Row="5" Grid.ColumnSpan="2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Text="Cancel" ></Button>
<Button Grid.Column="1" Text="Report Number"></Button>
</Grid>
</StackLayout>
</Grid>
</StackLayout>
</ScrollView>
</RefreshView>
</ContentPage.Content>
TargetDetailPage.xaml.cs:
public partial class TargetDetailPage : ContentPage
{
TargetDetailViewModel viewModel;
readonly int targetId;
public TargetDetailPage()
{
InitializeComponent();
}
public TargetDetailPage(TargetDetailViewModel viewModel)
{
InitializeComponent();
BindingContext = this.viewModel = viewModel;
}
public TargetDetailPage(int seledtedTargetId)
{
InitializeComponent();
targetId = seledtedTargetId;
}
protected override void OnAppearing()
{
base.OnAppearing();
if (viewModel.VerificationDetail == null)
viewModel.IsBusy = true;
}
}
TargetDetailViewModel .cs:
public class TargetDetailViewModel : BaseViewModel
{
public VerificationDetail VerificationDetail { get; set; }
public Target Target { get; set; }
public Command LoadTargetDetailCommand { get; set; }
public TargetDetailViewModel()
{
Title = "Verification Detail";
}
public TargetDetailViewModel(Target target)
{
Title = "Verification Detail";
Target = target;
LoadTargetDetailCommand = new Command(async () => await CreateVerification(target?.TargetId));
}
public async Task CreateVerification(int? targetId)
{
IsBusy = true;
try
{
if (targetId.HasValue)
{
VerificationDetail = await DataStoreVerificationDetail.CreateVerification(targetId.Value);
if (VerificationDetail != null && string.IsNullOrWhiteSpace(VerificationDetail.sms))
{
VerificationDetail.sms = "Verification Detail.";
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
}
DataStoreVerificationDetail.cs:
public async Task<VerificationDetail> CreateVerification(int taregtId)
{
var token = App.bearer_token;
Uri baseUri = new Uri(Constants.BaseURL);
var uri = new Uri(baseUri, "Api/Verifications");
HttpClient client = new HttpClient
{
MaxResponseContentBufferSize = 256000
};
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var httpContent = new StringContent(JsonConvert.SerializeObject(new { id = taregtId }), Encoding.UTF8, "application/json");
var response = await client.PostAsync(uri, httpContent);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var verificationDetail = JsonConvert.DeserializeObject<VerificationDetail>(content);
return verificationDetail; ;
}
return verificationDetail;
}
Edit: My problem is Detail View does not show data received from api. A blank view is shown without data before the asyn api call completed.
来源:https://stackoverflow.com/questions/62739541/xamarin-forms-load-a-detail-page-consuming-rest-api-onitemselected-of-listview