Invalid Cast Exception being thrown on button command.

Goobs1284Goobs1284 USMember ✭✭
edited January 2017 in Xamarin.Forms

I have a page that contains a listview. When a listview item is selected, I want that object to be passed into the next page to get the data specific to that object. However, when I try to do so, I keep getting an invalid cast exception although the functions are all passing/accepting the same object.

Here is the xaml/cs/viewmodel for the first page:

//xaml
    <ListView x:Name="JobListView"
              Grid.Column="0"
              Grid.Row="2"
              VerticalOptions="Fill"
              HorizontalOptions="Fill"
              ItemsSource="{Binding jobs}"
              SelectedItem="{Binding selectedJob, Mode=OneWayToSource}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout x:Name="ViewCellStackLayout"
                                 Orientation="Horizontal">
                        <Label x:Name="JobNameLabel"
                               Text="{Binding name}"/>
                        <Label x:Name="JobNumLabel"
                               Text="{Binding jobnum}"/>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <Button x:Name="JobTransferButton"
            Grid.Column="0"
            Grid.Row="3"
            VerticalOptions="End"
            HorizontalOptions="Fill"
            Text="Transfer Selected Job"
            Command="{Binding JobTransferCommand}"
            CommandParameter="{Binding selectedJob}"/>

//xaml.cs
    public JobSelectPage()
    {
        InitializeComponent();
        ((JobSelectViewModel)BindingContext).RefreshCommand.Execute(null);
    }

//viewmodel
    public RelayCommand<JcJob> JobTransferCommand
    {
        get
        {
            return _jobTransferCommand
                   ?? (_jobTransferCommand = new RelayCommand<JcJob>(
                       async job =>
                       {
                           try
                           {
                               if (!_jobTransferCommand.CanExecute(job)) { return; }

                               if (_navService.CurrentPageKey == ViewModelLocator.PageKeyJobTransferPage) return;
                               await _navService.NavigateTo(ViewModelLocator.PageKeyJobTransferPage, job);
                           }
                           catch (Exception ex)
                           {
                               var result = _dialog.ShowError(ex,
                                    ResourceConstants.PopupDialogGeneralError,
                                    ResourceConstants.PopupDialogOkButton,
                                    null);
                           }
                       }, (job => job != null)));
        }
    }

And the xaml.cs/viewmodel for the page I am going to:

//xaml.cs
    public JobTransferPage(JcJob job)
    {
        InitializeComponent();
        ((JobTransferViewModel)BindingContext).RefreshCommand.Execute(job);
    }

//viewmodel
    public RelayCommand<JcJob> RefreshCommand
    {
        get
        {
            return _refreshCommand
                   ?? (_refreshCommand = new RelayCommand<JcJob>(
                       async job =>
                       {
                           try
                           {
                               await Task.Delay(0);
                           }
                           catch (Exception ex)
                           {
                               var result = _dialog.ShowMessage(ex.Message,
                                   ResourceConstants.PopupDialogGeneralError,
                                   ResourceConstants.PopupDialogOkButton,
                                   null);
                           }

                       }));
        }
    }

And this is the line where I get the exception (this belongs to the page I am navigating to's constructor in the xaml.cs):

        ((JobTransferViewModel)BindingContext).RefreshCommand.Execute(job);

Best Answer

  • Goobs1284Goobs1284 US ✭✭
    Accepted Answer

    Thanks to @NMackay
    I was able to resolve my issue.

    In my JobTransferPage.xaml, my binding context was off:

    BindingContext="{Binding Source=x:Static mvvm:App.Locator}, Path=JobTabbed}"
    

    Should have been:

    BindingContext="{Binding Source={x:Static mvvm:App.Locator}, Path=JobTransfer}"
    

Answers

  • NMackayNMackay GBInsider, University mod
    edited January 2017

    @Goobs1284

    Seems okay, has your RelayCommand in JobTransferViewModel been declared with the correct signature? If you copied the declaration from JobSelectViewModel that RelayCommand doesn't expect a parameter.

    private RelayCommand<JcJob> _refreshCommand;
    

    Assuming the navigation service has found that page and correctly injected the object I'm not sure why that issue would be.

    In your JobTransfer page, stick a breakpoint on the line that executes the command just to see what the job param is set to before calling the command.

    public JobTransferPage(JcJob job)
        {
            InitializeComponent();
            ((JobTransferViewModel)BindingContext).RefreshCommand.Execute(job); << 
        }
    
  • Goobs1284Goobs1284 USMember ✭✭

    @NMackay

    Alright, so in my JobTransferViewModel, I have declared the private RelayCommand as:

    private RelayCommand<JcJob> _refreshCommand;
    

    When I insert a debug breakpoint at that line, job does contain the correct information that was selected from the list when the button was pressed.

    The only thing I can see now is this:

    public class JcJob : ObservableObject
    

    That is how I declare my JcJob class, I don't see why that is an issue, but I am wondering if because I derived from ObservableObject, that throws an error?

  • NMackayNMackay GBInsider, University mod

    @Goobs1284

    I can't see using ObservableObject would cause an issue, I've used that approach a few times.

    If you able to share the code I could have a closer look for you, PM me a private link or something and I'll look at it later. If it's an app in progress I know that is probably not an option, even a small repo project might help as I can't see what's causing the issue.

  • Goobs1284Goobs1284 USMember ✭✭
    Accepted Answer

    Thanks to @NMackay
    I was able to resolve my issue.

    In my JobTransferPage.xaml, my binding context was off:

    BindingContext="{Binding Source=x:Static mvvm:App.Locator}, Path=JobTabbed}"
    

    Should have been:

    BindingContext="{Binding Source={x:Static mvvm:App.Locator}, Path=JobTransfer}"
    
Sign In or Register to comment.