How to pass parametres through command?

michalgizamichalgiza Member ✭✭
edited January 5 in Xamarin.Forms

Hi there! :smile:

i've made some docs research about how to pass parameters though command but end up with example below. My goal is to pass string parameter though command from list view to new page as new background image but i ended with Unhandled Exception while trying to achive this. I don't understand x:refenrece to well for now so for any time spend for explanation of this i would be very appreciate.

Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object.

Code for new page with parameter passed by

public partial class Page1 : ContentPage
{
    public WasteModel wasteModel;
    public Page1()
    {
        InitializeComponent();

        //BackgroundImage = wasteModel.WasteMainBackground;

        ((NavigationPage)Application.Current.MainPage).BarBackgroundColor = Color.FromHex("#586d82");
        InfoImageButton.Clicked += InfoImageButton_Clicked;
    }

    private async void InfoImageButton_Clicked(object sender, EventArgs e)
    {
        await Navigation.PushAsync(new PageInfo());
    }
}
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="AppDemo.Page1"
         xmlns:vm="clr-namespace:AppDemo.ViewModels"
         NavigationPage.HasNavigationBar="True"
         BackgroundImage="{Binding WasteModel.WasteMainBackground}"
     >

MainPage code

<ListView x:Name="wastesListView"
              ItemsSource="{Binding Wastes}"
              HasUnevenRows="True" 
              Margin="10,20,5,150" 
              SeparatorVisibility="None"
              BackgroundColor="Transparent"

              >
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="3*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>

                        <ProgressBar x:Name="progressBar"
                                    Grid.RowSpan="2" Grid.Row="0" Grid.Column="0"
                                     BackgroundColor="Transparent"
                                     ProgressColor="#614c96"
                                     Progress="{Binding WasteCounter}"                                         
                                     />
                        <ImageButton x:Name="iconButton"
                                     Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" 
                                     WidthRequest="100"
                                     HeightRequest="100"
                                     Aspect="AspectFit"
                                     BackgroundColor="Transparent"
                                     Source="{Binding WasteIcon}"
                                     Command="{x:Binding Source={x:Reference wastesListView}, Path=BindingContext.NavigateCommand}"
                                     CommandParameter="{x:Binding .}">
                        </ImageButton>
                    </Grid>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

MainViewModel code:

    public class MainViewModel : BaseViewModel
{
    public WasteModel waste;
    readonly IPageServices _pageServices;
    readonly IWasteService wasteService;

    public ICommand NavigateCommand { get; }
    public MainViewModel(IPageServices pageServices)
    {
        this._pageServices = pageServices;

        Wastes = GetWastes();
        NavigateCommand = new Command(NavigateToNextPage);

    }


    public string WasteBackroundImage => waste.WasteMainBackground;
    public string WasteIcon => waste.WasteIcon;
    public double WasteCounter
    {
        get { return waste.WasteCounter; }
        set
        {
            if (WasteCounter != value) return;
            WasteCounter = value;
            OnPropertyChanged("WasteCounter");
        }
    }

    public ObservableRangeCollection<WasteModel> Wastes { get; }
    public ObservableRangeCollection<WasteModel> GetWastes()
    {
        var WasteList = new ObservableRangeCollection<WasteModel>()
        {
            new WasteModel()
            {
                WasteCounter=.2,    WasteIcon="cup.png",   WasteMainBackground="background1.png"
            }


        };
        return WasteList;
    }

    void NavigateToNextPage(object obj)
    {
        var page = new Page1();
        page.BindingContext = waste.WasteMainBackground;
        _pageServices.PushAsync(page);
    }

Again i would very appreciate for any help with this . Thank you in advance :smile:

Best Answer

Answers

  • michalgizamichalgiza Member ✭✭

    in short way i need your help to set good reference to pass background image property to new page acording to each item clicked (each item has different background image string to be displayed ). Thank you in advance for any help or guid how to do it :wink: :tired_face: :disappointed:

  • JohnHardmanJohnHardman GBUniversity mod

    @michalgiza

    You haven't said which line is throwing the NullReferenceException. Without that information, my guess would be that you are not setting waste and so it is still null when you try to dereference it. However, there are other possibilities (e.g. _pageServices could be null).

    You need to identify which line is throwing the exception. Check the Output window's Debug panel, or look at the call stack in the exception, or step through the code in the debugger.

  • michalgizamichalgiza Member ✭✭
    edited January 5

    Sorrry for that , exception is thrown at page 1 code behind

    public partial class Page1 : ContentPage
    {
        public WasteModel wasteModel;
        public Page1()
        {
            InitializeComponent();
        //Excetpions is thwrowing to this line 
            BackgroundImage = wasteModel.WasteMainBackground;
        }
    }
    

    Output from debugger:

    01-05 13:39:08.614 I/MonoDroid( 1052): UNHANDLED EXCEPTION:
    01-05 13:39:08.764 I/MonoDroid( 1052): System.NullReferenceException: Object reference not set to an instance of an object.
    01-05 13:39:08.764 I/MonoDroid( 1052):   at AppDemo.Page1..ctor () [0x0000f] in C:\Users\micha\OneDrive\Pulpit\Backup\Kopia_dziala_navigacja_listview\AppDemo\AppDemo\Page1.xaml.cs:23 
    01-05 13:39:08.764 I/MonoDroid( 1052):   at AppDemo.ViewModels.MainViewModel.NavigateToNextPage (System.Object obj) [0x00009] in C:\Users\micha\OneDrive\Pulpit\Backup\Kopia_dziala_navigacja_listview\AppDemo\AppDemo\ViewModels\MainViewModel.cs:125 
    01-05 13:39:08.764 I/MonoDroid( 1052):   at Xamarin.Forms.Command.Execute (System.Object parameter) [0x00000] in D:\a\1\s\Xamarin.Forms.Core\Command.cs:112 
    01-05 13:39:08.764 I/MonoDroid( 1052):   at Xamarin.Forms.ButtonElement.ElementClicked (Xamarin.Forms.VisualElement visualElement, Xamarin.Forms.Internals.IButtonElement ButtonElementManager) [0x00008] in D:\a\1\s\Xamarin.Forms.Core\ButtonElement.cs:60 
    01-05 13:39:08.764 I/MonoDroid( 1052):   at Xamarin.Forms.ImageButton.SendClicked () [0x00000] in D:\a\1\s\Xamarin.Forms.Core\ImageButton.cs:155 
    01-05 13:39:08.765 I/MonoDroid( 1052):   at Xamarin.Forms.Platform.Android.FastRenderers.ButtonElementManager.OnClick (Xamarin.Forms.VisualElement element, Xamarin.Forms.IButtonController buttonController, Android.Views.View v) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.Android\FastRenderers\ButtonElementManager.cs:31 
    01-05 13:39:08.765 I/MonoDroid( 1052):   at Xamarin.Forms.Platform.Android.ImageButtonRenderer.Android.Views.View.IOnClickListener.OnClick (Android.Views.View v) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.Android\AppCompat\ImageButtonRenderer.cs:287 
    01-05 13:39:08.765 I/MonoDroid( 1052):   at Android.Views.View+IOnClickListenerInvoker.n_OnClick_Landroid_view_View_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_v) [0x00011] in <1219ce5aae934ab095dc0e05b2110050>:0 
    01-05 13:39:08.765 I/MonoDroid( 1052):   at (wrapper dynamic-method) System.Object.26(intptr,intptr,intptr)
    01-05 13:39:08.818 W/zygote  ( 1052): JNI RegisterNativeMethods: attempt to register 0 native methods for android.runtime.JavaProxyThrowable
    01-05 13:39:08.844 D/Mono    ( 1052): DllImport searching in: '__Internal' ('(null)').
    01-05 13:39:08.844 D/Mono    ( 1052): Searching for 'java_interop_jnienv_throw'.
    01-05 13:39:08.844 D/Mono    ( 1052): Probing 'java_interop_jnienv_throw'.
    01-05 13:39:08.844 D/Mono    ( 1052): Found as 'java_interop_jnienv_throw'.
    Unhandled Exception:
    
    System.NullReferenceException: Object reference not set to an instance of an object.
    
  • michalgizamichalgiza Member ✭✭
    edited January 5

    @JohnHardman
    Your anwser follow me to do this:
    Func responsible to move to next page

            void NavigateToNextPage(object obj)
            {
                IsVisible = true;
    
               var page = new Page1(waste);
                _pageServices.PushAsync(page);
            }
    

    In Page1.xaml.cs file

            public Page1(WasteModel wasteModel)
            {
                InitializeComponent();
    
                wasteModel = new WasteModel();
                BackgroundImage = wasteModel.WasteMainBackground;
    
    
                ((NavigationPage)Application.Current.MainPage).BarBackgroundColor = Color.FromHex("#586d82");
                InfoImageButton.Clicked += InfoImageButton_Clicked;
            }
    
    

    Now app not throw exception as you suggest to initialize model , but don't send background image to new page :disappointed:

  • michalgizamichalgiza Member ✭✭

    So i think that it is my lack of understanding how mvvm pattern works , would be easier to create new view model for Page1 and inhirit from MainViewModel to display this background image for WasteModel object ? Am i follow good direction or just moving away from solution of my problem ?

  • JohnHardmanJohnHardman GBUniversity mod

    @michalgiza said:
    In Page1.xaml.cs file

            public Page1(WasteModel wasteModel)
            {
                InitializeComponent();
    
                wasteModel = new WasteModel();
                BackgroundImage = wasteModel.WasteMainBackground;
    
                
                ((NavigationPage)Application.Current.MainPage).BarBackgroundColor = Color.FromHex("#586d82");
                InfoImageButton.Clicked += InfoImageButton_Clicked;
            }
    
    

    Now you are overwriting the wasteModel that was passed in to the Page1 constructor as a parameter. You do not want the wasteModel = new WasteModel(); in the Page1 constructor. Instead, you need to ensure that your NavigateToNextPage method passes the correct (non-null) value to the Page1 constructor.

    (The code could be tidied up, and MVVM practices made more explicit, but I'm ignoring those for the moment in order to nudge you towards a working system).

Sign In or Register to comment.