You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin TabbedPage绑定自定义类启动触发TargetInvocationException求助

TargetInvocationException when Binding ViewModels to TabbedPage in Xamarin.Forms

Hey folks, I'm hitting a TargetInvocationException right when my Xamarin.Forms app starts up, and it happens when I try to bind custom ViewModels to the two child ContentPages in my TabbedPage. Let me share my code and see if anyone can spot what's going wrong.

My TabbedPage XAML

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" 
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
            x:Class="DownToledoAPP.Views.InfoPage">
    <ContentPage Icon="tablon.png" BackgroundColor="#3A6DC8" x:Name="tablonpage">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <ListView x:Name="tablon" Grid.Row="0" 
                      SelectedItem="{Binding Noticiaelegida}" 
                      ItemsSource="{Binding Noticias}" >
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <Label Grid.Row="0" Text="{Binding titulo}" FontSize="Large"/>
                            <Label Grid.Row="1" Text="{Binding descripcion}" FontSize="Medium"/>
                            <Grid Grid.Row="2">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <Switch Grid.Column="0" Grid.Row="0" IsToggled="{Binding enprogreso}"/>
                                <Label Grid.Row="0" Grid.Column="1" Text="En progreso"/>
                                <Label Grid.Column="0" Grid.Row="1" Text="{Binding responsable}"/>
                            </Grid>
                        </Grid>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <Button x:Name="newnoticia" BackgroundColor="#FFCA02" Grid.Row="1" 
                    FontFamily="Cooper Black" TextColor="White" 
                    HorizontalOptions="Center" Text="Abrir nueva actividad"/>
        </Grid>
    </ContentPage>
    <ContentPage Icon="actividades.png" BackgroundColor="#3A6DC8" x:Name="actividadespage">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <ListView x:Name="actividades" Grid.Row="0" 
                      ItemsSource="{Binding Actividades}" 
                      SelectedItem="{Binding Actividadelegida}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <Label Grid.Row="0" FontSize="Large" Text="{Binding nombre}"/>
                            <Label Grid.Row="1" Text="{Binding descripcion}"/>
                            <Label Grid.Row="2" FontSize="Small" Text="{Binding horario}"/>
                            <Grid Grid.Row="3">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <Label Grid.Column="0" Text="{Binding responsable}"/>
                                <Label Grid.Column="1" Text="{Binding localizacion}"/>
                            </Grid>
                        </Grid>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <Button x:Name="newactividad" BackgroundColor="#FFCA02" Grid.Row="1" 
                    FontFamily="Cooper Black" TextColor="White" 
                    HorizontalOptions="Center" Text="Abrir nueva noticia"/>
        </Grid>
    </ContentPage>
</TabbedPage>

Code-behind for InfoPage

public partial class InfoPage : TabbedPage 
{ 
    private CWS cws; 
    private DatosUsuario actualusuario; 

    public InfoPage (string text) 
    { 
        InitializeComponent (); 
        cws = new CWS(); 
        actualusuario = new DatosUsuario(); 
        actualusuario=cws.DescargarInfousuario(text); 
        var alltablon= cargartablon(); 
        var actividades = cargaractividades(); 
        image.Source = actualusuario.foto; 
        name.Text = actualusuario.nombre + " " + actualusuario.apellido1 + " " + actualusuario.apellido2 + " Alias:" + actualusuario.nombreuser; 
        logout.Clicked += salir; 
        userinfo.Clicked += change; 
        newnoticia.Clicked += crearnoticia; 
        newactividad.Clicked += crearactividad; 
        tablonpage.BindingContext = new ViewModel.InfoNoticiasModel(alltablon, actualusuario.idusuario, this); 
        actividadespage.BindingContext = new ViewModel.InfoViewModel(actividades, actualusuario.idusuario, this); 
    } 

    private async void crearactividad(object sender, EventArgs e) 
    { 
        await Navigation.PushAsync(new DetailPage(null, null, "Actividad", actualusuario.idusuario)); 
    } 

    private async void crearnoticia(object sender, EventArgs e) 
    { 
        await Navigation.PushAsync(new DetailPage(null, null, "Noticia", actualusuario.idusuario)); 
    } 

    private List<ActividadesMVVM> cargaractividades() 
    { 
        var noticias = cws.DescargarActividades(actualusuario.idusuario.ToString(),actualusuario.idrol.ToString()); 
        var listamvvm = new List<ActividadesMVVM>(); 
        for (int i = 0; i < noticias.Count; i++) 
        { 
            var actividad = new ActividadesMVVM(); 
            var creador = cws.DescargarNombre(noticias[i].idresponsable.ToString()); 
            actividad.descripcion = noticias[i].descripcion; 
            actividad.horario = noticias[i].horario; 
            actividad...
    }
}

Let's Troubleshoot This

First off, TargetInvocationException is almost always a wrapper for an inner exception that's the real culprit. So your first step should be to dig into that inner exception to get the actual error message.

Step 1: Capture the Inner Exception

Wrap your constructor code in a try-catch block to log or inspect the inner exception:

public InfoPage(string text)
{
    try
    {
        InitializeComponent();
        // Rest of your constructor code here
    }
    catch (TargetInvocationException ex)
    {
        var realException = ex.InnerException;
        Console.WriteLine($"Root cause: {realException.Message}\nStack trace: {realException.StackTrace}");
        throw; // Re-throw to keep debugging flow
    }
}

Step 2: Stop Doing Network Calls in the Constructor

Your code is making synchronous network requests (cws.DescargarInfousuario, cws.DescargarActividades) directly in the constructor. This blocks the UI thread and is a common source of exceptions in Xamarin. Move this logic to an async method like OnAppearing:

public InfoPage(string text)
{
    InitializeComponent();
    // Only set up event handlers here
    logout.Clicked += salir;
    userinfo.Clicked += change;
    newnoticia.Clicked += crearnoticia;
    newactividad.Clicked += crearactividad;
}

protected override async void OnAppearing()
{
    base.OnAppearing();
    try
    {
        cws = new CWS();
        // Wrap sync calls in Task.Run to avoid blocking UI, or better yet, use async versions of your CWS methods
        actualusuario = await Task.Run(() => cws.DescargarInfousuario(text));
        var alltablon = await Task.Run(() => cargartablon());
        var actividades = await Task.Run(() => cargaractividades());

        // Update UI and set BindingContexts once data is loaded
        image.Source = actualusuario.foto;
        name.Text = $"{actualusuario.nombre} {actualusuario.apellido1} {actualusuario.apellido2} Alias:{actualusuario.nombreuser}";
        
        tablonpage.BindingContext = new ViewModel.InfoNoticiasModel(alltablon, actualusuario.idusuario, this);
        actividadespage.BindingContext = new ViewModel.InfoViewModel(actividades, actualusuario.idusuario, this);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Failed to load data: {ex.Message}");
        // Show a user-friendly error message here
    }
}

Step 3: Validate Your ViewModels

Make sure your InfoNoticiasModel and InfoViewModel are properly implemented:

  • They should implement INotifyPropertyChanged so bindings work correctly.
  • All properties referenced in your XAML (like Noticias, Actividades, Noticiaelegida) must exist and match the exact casing.
  • Add null checks in your ViewModel constructors—if alltablon or actividades is null, handle it gracefully instead of letting it throw.

Step 4: Fix Incomplete Data Loading

Your cargaractividades method cuts off mid-implementation. Make sure you're fully initializing each ActividadesMVVM object and adding it to the list. Also, add null checks for the data returned by cws.DescargarActividades:

private List<ActividadesMVVM> cargaractividades()
{
    var noticias = cws.DescargarActividades(actualusuario.idusuario.ToString(), actualusuario.idrol.ToString());
    var listamvvm = new List<ActividadesMVVM>();
    
    // Guard against null data
    if (noticias == null) return listamvvm;
    
    for (int i = 0; i < noticias.Count; i++)
    {
        var actividad = new ActividadesMVVM();
        var creador = cws.DescargarNombre(noticias[i].idresponsable.ToString());
        
        actividad.descripcion = noticias[i].descripcion;
        actividad.horario = noticias[i].horario;
        actividad.nombre = noticias[i].nombre; // Make sure you set all required properties
        actividad.responsable = creador;
        actividad.localizacion = noticias[i].localizacion;
        
        listamvvm.Add(actividad);
    }
    return listamvvm;
}

Step 5: Ensure UI Thread Safety

When setting BindingContexts, make sure you're doing it on the UI thread. Wrap those lines in Device.BeginInvokeOnMainThread if you're running code in a background task:

Device.BeginInvokeOnMainThread(() =>
{
    tablonpage.BindingContext = new ViewModel.InfoNoticiasModel(alltablon, actualusuario.idusuario, this);
    actividadespage.BindingContext = new ViewModel.InfoViewModel(actividades, actualusuario.idusuario, this);
});

内容的提问来源于stack exchange,提问作者Krever

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:13:11