[XAMARIN FORMS] problem of the link between my xaml view (with a picker) and the viewmodel

camillecamille Member ✭✭
edited January 28 in Xamarin.Forms

Hello everyone,

I have a small problem, I explain myself:

here's what I did, I have a page with buttons (with different values) and a picker (see xaml code), when the user clicks on a button, normally the picker selection list proposes things that are linked to the value of my button through lists (see my view model code). Except it doesn't work!

In my opinion it is because of the static type that is on some of my lists and methods. So my picker which has a binding on one of my lists does not display my selection because it cannot access my list because it is in static and not a constructor (in which I call the element of my binding).

Do you have a solution for me?

If you can't understand me, don't hesitate to ask me questions?

you will find the different files with my code below.

Sincerely
Camille

xaml code :

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="PolQual.Views.StatementReferencielPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:PolQual.Views"
    xmlns:viewModels="clr-namespace:PolQual.ViewModels;assembly=PolQual"
    Title="Accueil">

    <ContentPage.BindingContext>
        <viewModels:StatementReferencielPageModel />
    </ContentPage.BindingContext>

    <ContentPage.Content>

        <StackLayout>

            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="10*" />
                    <RowDefinition Height="15*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100*" />
                </Grid.ColumnDefinitions>

                <Label
                    Grid.Row="0"
                    Grid.Column="0"
                    FontSize="25"
                    HorizontalOptions="Center"
                    Text="Information sur le relevé référenciel" />

            </Grid>

            <ScrollView>
                <Grid x:Name="gridLayout" />
            </ScrollView>

            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="2*" />
                    <RowDefinition Height="3*" />
                    <RowDefinition Height="8*" />
                    <RowDefinition Height="2*" />
                    <RowDefinition Height="3*" />
                    <RowDefinition Height="6*" />
                    <RowDefinition Height="3*" />
                    <RowDefinition Height="6*" />
                    <RowDefinition Height="3*" />
                    <RowDefinition Height="6*" />
                    <RowDefinition Height="5*" />
                    <RowDefinition Height="6*" />
                    <RowDefinition Height="1*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="25*" />
                    <ColumnDefinition Width="50*" />
                    <ColumnDefinition Width="25*" />
                </Grid.ColumnDefinitions>

                <Label
                    Grid.Row="1"
                    Grid.Column="1"
                    FontSize="15"
                    Text="Veuillez sélectioner le secteur :" />

                <Picker
                    x:Name="PickerSectorsLists"
                    Title="Sélectionner votre secteur"
                    Grid.Row="2"
                    Grid.Column="1"
                    ItemDisplayBinding="{Binding Value}"
                    ItemsSource="{Binding SectorsFindLists}"
                    SelectedItem="{Binding SelectedSector}" />

                <Label
                    Grid.Row="4"
                    Grid.Column="1"
                    FontSize="15"
                    Text="{Binding ShowHouseholdTrash}" />

                <Switch
                    x:Name="SwitchHousehodTrash"
                    Grid.Row="5"
                    Grid.Column="1"
                    HorizontalOptions="Start"
                    IsToggled="{Binding HouseholdTrash}" />

                <Label
                    Grid.Row="6"
                    Grid.Column="1"
                    FontSize="15"
                    Text="{Binding ShowBoxboard}" />

                <Switch
                    x:Name="SwitchBoxboard"
                    Grid.Row="7"
                    Grid.Column="1"
                    HorizontalOptions="Start"
                    IsToggled="{Binding Boxboard}" />

                <Label
                    Grid.Row="8"
                    Grid.Column="1"
                    FontSize="15"
                    Text="{Binding ShowGlass}" />

                <Switch
                    x:Name="SwitchGlass"
                    Grid.Row="9"
                    Grid.Column="1"
                    HorizontalOptions="Start"
                    IsToggled="{Binding Glass}" />

                <Button
                    Grid.Row="11"
                    Grid.Column="1"
                    BackgroundColor="#2196f3"
                    Clicked="GoToAssesmentGrid"
                    FontSize="20"
                    Text="Valider les informations"
                    TextColor="White" />

            </Grid>

        </StackLayout>

    </ContentPage.Content>
</ContentPage>

Behind code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using PolQual.ViewModels;

namespace PolQual.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class StatementReferencielPage : ContentPage
    {
        public StatementReferencielPage()
        {
            InitializeComponent ();
            BindingContext = new StatementReferencielPageModel();
            gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
            gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
            gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
            gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
            gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
            gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
            gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
            //collmun
            gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(25, GridUnitType.Star) });
            gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(50, GridUnitType.Star) });
            gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(25, GridUnitType.Star) });

            var PolesListsIndex = 0;

            for (int columnIndex = 1; columnIndex < 2; columnIndex++)
            {
                for (int rowIndex = 0; rowIndex < 7; rowIndex++)
                {
                    if (PolesListsIndex >= StatementReferencielPageModel.PolesLists.Count<Pole>())
                    {
                        return;
                    }
                    var poles = StatementReferencielPageModel.PolesLists[PolesListsIndex];
                    PolesListsIndex += 1;

                    var button = new Button()
                    {                   
                        Text = poles.Name,
                        BackgroundColor = Color.FromHex(poles.Color),
                        HorizontalOptions = LayoutOptions.Center,
                        VerticalOptions = LayoutOptions.Center,
                        WidthRequest = 280,
                    };
                    string request = StatementReferencielPageModel.PolesLists[rowIndex].Name;
                    button.Clicked += delegate { MaFunction(request); };// anonymous method
                    gridLayout.Children.Add(button, columnIndex, rowIndex);  

                }
            }
        }

        public static void MaFunction(string polename)
        {
           StatementReferencielPageModel.FindPoleName(polename);
        }

        public void GoToAssesmentGrid(object sender, System.EventArgs e)
        {
            if (PickerSectorsLists.SelectedIndex == -1) 
            {
                DisplayAlert("Erreur de saisie", "Veuillez séléctioner un secteur svp! ", "D'accord");
            }
            else
            {
                var page = new AssesmentGridPage();
                Navigation.PushAsync(page);
            }
         }
    }
}

view Model code :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using Xamarin.Forms;
using PolQual.Views;

namespace PolQual.ViewModels
{
    public class StatementReferencielPageModel : INotifyPropertyChanged
    {
        private static List<Sector> _sectorsLists;
        public static List<Sector> SectorsLists { get => _sectorsLists; set => _sectorsLists = value; }

        private readonly List<Sector> sectorsFindLists;
        private static List<Sector> _sectorsFindLists;
        public static List<Sector> SectorsFindLists { get => _sectorsFindLists; set => _sectorsFindLists = value; }

        private static List<Pole> _polesLists;
        public static List<Pole> PolesLists { get => _polesLists; set => _polesLists = value; }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string propertyname = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
        }

        private bool _boxboard { get; set; }
        public bool Boxboard
        {
            get { return _boxboard; }
            set
            {
                _boxboard = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(ShowBoxboard));
            }
        }

        private bool _glass { get; set; }
        public bool Glass
        {
            get { return _glass; }
            set
            {
                _glass = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(ShowGlass));
            }
        }

        private bool _householdTrash { get; set; }
        public bool HouseholdTrash
        {
            get { return _householdTrash; }
            set
            {
                _householdTrash = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(ShowHouseholdTrash));
            }
        }

        private Sector _selectedSector { get; set; }
        public Sector SelectedSector
        {
            get { return _selectedSector; }
            set
            {
                if (_selectedSector != value)
                {
                    _selectedSector = value;
                    // que faire quand l'élèment est sélectionné !
                }
            }
        }

        public StatementReferencielPageModel()
        {
            SectorsLists = GetSectors().OrderBy(t => t.Key).ToList();
            SectorsFindLists = GetSectors().OrderBy(t => t.Key).ToList();
            PolesLists = GetPoles().OrderBy(t => t.Key).ToList();
        }

        public List<Sector> GetSectors()
        {
            var Sectors = new List<Sector>()
            {
                //Erdre et cens
                new Sector() { Key = 0, Value = "Sautron", PoleName="Erdre et cens" },
                new Sector() { Key = 1, Value = "Orvault", PoleName="Erdre et cens" },
                new Sector() { Key = 2, Value = "Nantes Nord", PoleName="Erdre et cens" },
                new Sector() { Key = 3, Value = "La-Chapelle-Sur-Erdre", PoleName="Erdre et cens" },
                // Erdre et Loire
                new Sector() { Key = 4, Value = "Mauves-Sur-Loire", PoleName="Erdre et Loire" },
                new Sector() { Key = 5, Value = "Carquefou", PoleName="Erdre et Loire" },
                new Sector() { Key = 6, Value = "Thouré sur Loire", PoleName="Erdre et Loire" },
                new Sector() { Key = 7, Value = "Sainte Luce sur Loire", PoleName="Erdre et Loire" },
                new Sector() { Key = 8, Value = "Nantes Erdre", PoleName="Erdre et Loire" },
                new Sector() { Key = 9, Value = "Doulon", PoleName="Erdre et Loire" },
                //Loire-Sèvre et Vignoble
                new Sector() { Key = 10, Value = "Rezé", PoleName="Loire-Sèvre et Vignoble" },
                new Sector() { Key = 11, Value = "Les Sornières", PoleName="Loire-Sèvre et Vignoble" },
                new Sector() { Key = 12, Value = "Vertou", PoleName="Loire-Sèvre et Vignoble" },
                new Sector() { Key = 13, Value = "Saint Sébastien sur Loire", PoleName="Loire-Sèvre et Vignoble" },
                new Sector() { Key = 14, Value = "Base Goulaine", PoleName="Loire-Sèvre et Vignoble" },
                new Sector() { Key = 15, Value = "Nantes sud", PoleName="Loire-Sèvre et Vignoble" },
                //Sud-Ouest
                new Sector() { Key = 16, Value = "Bouchenais", PoleName="Sud-Ouest" },
                new Sector() { Key = 17, Value = "Saint-Aignan-Grandlieu", PoleName="Sud-Ouest" },
                new Sector() { Key = 18, Value = "Bouaye", PoleName="Sud-Ouest" },
                new Sector() { Key = 19, Value = "Saint-Leger-Les-Vignes", PoleName="Sud-Ouest" },
                new Sector() { Key = 20, Value = "Brains", PoleName="Sud-Ouest" },
                new Sector() { Key = 21, Value = "La-Montagne", PoleName="Sud-Ouest" },
                new Sector() { Key = 22, Value = "Saint-Jean-De-Boiseau", PoleName="Sud-Ouest" },
                new Sector() { Key = 23, Value = "Le Pellerin", PoleName="Sud-Ouest" },
                //Loire-Chézine
                new Sector() { Key = 24, Value = "Couëron", PoleName="Loire-Chézine" },
                new Sector() { Key = 25, Value = "Saint-Herblain", PoleName="Loire-Chézine" },
                new Sector() { Key = 26, Value = "Indre", PoleName="Loire-Chézine" },
                //Nantes-Ouest
                new Sector() { Key = 27, Value = "Bellevue-Chantenay-Sainte-Anne", PoleName="Nantes-Ouest" },
                new Sector() { Key = 28, Value = "Dervallière-Zola", PoleName="Nantes-Ouest" },
                new Sector() { Key = 29, Value = "Breil-Barberie", PoleName="Nantes-Ouest" },
                new Sector() { Key = 30, Value = "Hauts Pavés Saint Félix", PoleName="Nantes-Ouest" },
                //Nantes-Loire
                new Sector() { Key = 31, Value = "Malakof-Saint-Donatien", PoleName="Nantes-Loire" },
                new Sector() { Key = 32, Value = "Centre Ville", PoleName="Nantes-Loire" },
                new Sector() { Key = 33, Value = "île de Nantes", PoleName="Nantes-Loire" },

            };
            return Sectors;
        }

        public List<Pole> GetPoles()
        {
            var Poles = new List<Pole>()
            {
                new Pole { Key = 1, Name = "Erdre et Cens", Color = "ffccd5"},
                new Pole { Key = 2, Name = "Erdre et Loire", Color = "ff4d4d"},
                new Pole { Key = 3, Name = "Loire-Sèvre et vignoble", Color = "ff9933"},
                new Pole { Key = 4, Name = "Sud-Ouest", Color = "bfbfbf"},
                new Pole { Key = 5, Name = "Loire-chézine", Color = "ffff4d"},
                new Pole { Key = 6, Name = "Nantes-Ouest", Color = "3385ff"},
                new Pole { Key = 7, Name = "Nantes-Loire", Color = "53c653"},
            };
            return Poles;
        }

        public static void FindPoleName(string polename)
        {
            for (int search = 0; search < SectorsLists.Count(); search++)
            {
                if (SectorsLists[search].PoleName == polename)
                {
                    SectorsFindLists.Add(new Sector() {Key = search, Value = SectorsLists[search].Value, PoleName = polename });
                }
            }
        }

        public string ShowBoxboard
        {
            get
            {
                return $"{(_boxboard ? "Jour de collecte des cartons : oui " : "Jour de collecte des cartons : non")}";
            }
        }

        public string ShowGlass
        {
            get
            {
                return $"{(_glass ? "Jour de collecte du verre : oui " : "Jour de collecte du verre : non")}";
            }
        }

        public string ShowHouseholdTrash
        {
            get
            {
                return $"{(_householdTrash ? "Jour de collecte des Ordure ménagère : oui " : "Jour de collecte des Ordure ménagère : non")}";
            }
        }
    }

    public class Sector
    {
        private int _key;
        public int Key { get => _key; set => _key = value; }

        private string _value;
        public string Value { get => _value; set => _value = value; }

        private string _poleName;
        public string PoleName { get => _poleName; set => _poleName = value; }
    }

    public class Pole
    {
        private int _key;
        public int Key { get => _key; set => _key = value; }

        private string _color;
        public string Color { get => _color; set => _color = value; }

        private string _name;
        public string Name { get => _name; set => _name = value; }
    }
}

Posts

  • TaylorDTaylorD USMember ✭✭✭

    Your UI's BindingContext is set to the view model correctly but you are modifying your static properties and lists. A UI can't binding to static members. UI's can only bind to public instance properties. I suggest changing your ViewModel to have non static properties. Also change them to ObservableCollections as well to allow the UI to automatically get notified of the updated lists.

    ViewModel (OLD)

    private static List<Pole> _polesLists;
    public static List<Pole> PolesLists { get => _polesLists; set => _polesLists = value; }
    

    ViewModel (NEW)

    public ObservableCollection<Pole> PolesCollection { get; set; } = new ObservableCollection<Pole>();
    

    Then modify PolesCollection when adding and finding poles in your VM. Also, FindPoles will need to not be static as well.

    Your UI will need to keep a reference to your VM that you set as your BindingContext.

    View.cs (OLD)

    public StatementReferencielPage()
    {
        InitializeComponent();
    
        BindingContext = new StatementReferencielPageModel();
    
        // Other control initialization below
    }
    
    public static void MaFunction(string polename)
    {
        StatementReferencielPageModel.FindPoleName(polename);
    }
    

    View.cs (NEW)

    public StatementReferencielPage()
    {
        InitializeComponent();
    
        _viewModel = new StatementReferencielPageModel();
        BindingContext = _viewModel;
    
        // Other control initialization below
    }
    
    public void MaFunction(string polename)
    {
        _viewModel.FindPoleName(polename);
    }
    

    Hopefully this helps you!

  • camillecamille Member ✭✭

    first of all thank you for your answer

    but I don't see how I can do anything wrong to call my function "My Function" and the observableCollection "PolesCollection" which is in my view model from the behind file without putting them in static.

    Because if as you say I remove the static property I can no longer access my attributes or functions from my behind code

    I have one last question concerning the ObservablesCollection, is it considered as a list or not at all because I confess to having already looked at the Microsoft site without really understanding how it works.

  • TaylorDTaylorD USMember ✭✭✭

    You are able to call and reference those methods and collections in your StatementReferencielPageModel when you save the reference to it like I showed in the View.cs (NEW) code. When you set your BindingContext you must save that reference to be able to call the appropriate view model method in your MaFunction.

    To be able to Bind your lists properly, they cannot be static.

    An ObservableCollection is a type of collection that provides all the functionality that a List does, but when ObservableCollection's are binded to your view correctly, allows the UI to automatically be updated when an object (or Pole in your case) is added or removed from that collection.

  • camillecamille Member ✭✭
    edited January 28

    Thank you once again for your explanations and the time you are taking to help me.

    I changed my code before the compilation my ide does not indicate any problem but during the compilation here is the error that appears:

    Unhandled Exception:

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

    the error appears on the behind page on line 42

    Do you have any idea where this came from?

    code behind :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;
    using PolQual.ViewModels;
    
    namespace PolQual.Views
    {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class StatementReferencielPage : ContentPage
        {
            public StatementReferencielPageModel _viewModel { get; }
    
            public StatementReferencielPage()
            {
                InitializeComponent ();
    
                BindingContext = _viewModel;
    
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                //collmun
                gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(25, GridUnitType.Star) });
                gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(50, GridUnitType.Star) });
                gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(25, GridUnitType.Star) });
    
                var PolesListsIndex = 0;
    
                for (int columnIndex = 1; columnIndex < 2; columnIndex++)
                {
                    for (int rowIndex = 0; rowIndex < 7; rowIndex++)
                    {
                        if (PolesListsIndex >= _viewModel.PolesCollection.Count<Pole>())
                        {
                            return;
                        }
                        var poles = _viewModel.PolesCollection[PolesListsIndex];
                        PolesListsIndex += 1;
    
                        var button = new Button()
                        {                   
                            Text = poles.Name,
                            BackgroundColor = Color.FromHex(poles.Color),
                            HorizontalOptions = LayoutOptions.Center,
                            VerticalOptions = LayoutOptions.Center,
                            WidthRequest = 280,
                        };
                        string request = _viewModel.PolesCollection[rowIndex].Name;
                        button.Clicked += delegate { MaFunction(request); };// anonymous method
                        gridLayout.Children.Add(button, columnIndex, rowIndex);  
    
                    }
                }
            }
    
            public void MaFunction(string polename)
            {
                _viewModel.FindPoleName(polename);
            }
    
            public void GoToAssesmentGrid(object sender, System.EventArgs e)
            {
                if (PickerSectorsLists.SelectedIndex == -1) 
                {
                    DisplayAlert("Erreur de saisie", "Veuillez séléctioner un secteur svp! ", "D'accord");
                }
                else
                {
                    var page = new AssesmentGridPage();
                    Navigation.PushAsync(page);
                }
             }
        }
    }
    

    code viewModel :

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Text;
    using Xamarin.Forms;
    using PolQual.Views;
    using System.Collections.ObjectModel;
    
    namespace PolQual.ViewModels
    {
        public class StatementReferencielPageModel : INotifyPropertyChanged
        {
            private List<Sector> _sectorsLists;
            public List<Sector> SectorsLists { get => _sectorsLists; set => _sectorsLists = value; }
    
            private List<Sector> _sectorsFindLists;
            public List<Sector> SectorsFindLists { get => _sectorsFindLists; set => _sectorsFindLists = value; }
    
            private static ObservableCollection<Pole> _polesCollection;
            public ObservableCollection<Pole> PolesCollection { get => _polesCollection; set => _polesCollection = value; }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            public void OnPropertyChanged([CallerMemberName] string propertyname = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
    
            private bool _boxboard { get; set; }
            public bool Boxboard
            {
                get { return _boxboard; }
                set
                {
                    _boxboard = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(ShowBoxboard));
                }
            }
    
            private bool _glass { get; set; }
            public bool Glass
            {
                get { return _glass; }
                set
                {
                    _glass = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(ShowGlass));
                }
            }
    
            private bool _householdTrash { get; set; }
            public bool HouseholdTrash
            {
                get { return _householdTrash; }
                set
                {
                    _householdTrash = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(ShowHouseholdTrash));
                }
            }
    
            private Sector _selectedSector { get; set; }
            public Sector SelectedSector
            {
                get { return _selectedSector; }
                set
                {
                    if (_selectedSector != value)
                    {
                        _selectedSector = value;
                        // que faire quand l'élèment est sélectionné !
                    }
                }
            }
    
            public StatementReferencielPageModel()
            {
                SectorsLists = GetSectors().OrderBy(t => t.Key).ToList();
                SectorsFindLists = GetSectors().OrderBy(t => t.Key).ToList();
                PolesCollection = GetPoles();
            }
    
            public List<Sector> GetSectors()
            {
                var Sectors = new List<Sector>()
                {
                    //Erdre et cens
                    new Sector() { Key = 0, Value = "Sautron", PoleName="Erdre et cens" },
                    new Sector() { Key = 1, Value = "Orvault", PoleName="Erdre et cens" },
                    new Sector() { Key = 2, Value = "Nantes Nord", PoleName="Erdre et cens" },
                    new Sector() { Key = 3, Value = "La-Chapelle-Sur-Erdre", PoleName="Erdre et cens" },
                    // Erdre et Loire
                    new Sector() { Key = 4, Value = "Mauves-Sur-Loire", PoleName="Erdre et Loire" },
                    new Sector() { Key = 5, Value = "Carquefou", PoleName="Erdre et Loire" },
                    new Sector() { Key = 6, Value = "Thouré sur Loire", PoleName="Erdre et Loire" },
                    new Sector() { Key = 7, Value = "Sainte Luce sur Loire", PoleName="Erdre et Loire" },
                    new Sector() { Key = 8, Value = "Nantes Erdre", PoleName="Erdre et Loire" },
                    new Sector() { Key = 9, Value = "Doulon", PoleName="Erdre et Loire" },
                    //Loire-Sèvre et Vignoble
                    new Sector() { Key = 10, Value = "Rezé", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 11, Value = "Les Sornières", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 12, Value = "Vertou", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 13, Value = "Saint Sébastien sur Loire", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 14, Value = "Base Goulaine", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 15, Value = "Nantes sud", PoleName="Loire-Sèvre et Vignoble" },
                    //Sud-Ouest
                    new Sector() { Key = 16, Value = "Bouchenais", PoleName="Sud-Ouest" },
                    new Sector() { Key = 17, Value = "Saint-Aignan-Grandlieu", PoleName="Sud-Ouest" },
                    new Sector() { Key = 18, Value = "Bouaye", PoleName="Sud-Ouest" },
                    new Sector() { Key = 19, Value = "Saint-Leger-Les-Vignes", PoleName="Sud-Ouest" },
                    new Sector() { Key = 20, Value = "Brains", PoleName="Sud-Ouest" },
                    new Sector() { Key = 21, Value = "La-Montagne", PoleName="Sud-Ouest" },
                    new Sector() { Key = 22, Value = "Saint-Jean-De-Boiseau", PoleName="Sud-Ouest" },
                    new Sector() { Key = 23, Value = "Le Pellerin", PoleName="Sud-Ouest" },
                    //Loire-Chézine
                    new Sector() { Key = 24, Value = "Couëron", PoleName="Loire-Chézine" },
                    new Sector() { Key = 25, Value = "Saint-Herblain", PoleName="Loire-Chézine" },
                    new Sector() { Key = 26, Value = "Indre", PoleName="Loire-Chézine" },
                    //Nantes-Ouest
                    new Sector() { Key = 27, Value = "Bellevue-Chantenay-Sainte-Anne", PoleName="Nantes-Ouest" },
                    new Sector() { Key = 28, Value = "Dervallière-Zola", PoleName="Nantes-Ouest" },
                    new Sector() { Key = 29, Value = "Breil-Barberie", PoleName="Nantes-Ouest" },
                    new Sector() { Key = 30, Value = "Hauts Pavés Saint Félix", PoleName="Nantes-Ouest" },
                    //Nantes-Loire
                    new Sector() { Key = 31, Value = "Malakof-Saint-Donatien", PoleName="Nantes-Loire" },
                    new Sector() { Key = 32, Value = "Centre Ville", PoleName="Nantes-Loire" },
                    new Sector() { Key = 33, Value = "île de Nantes", PoleName="Nantes-Loire" },
    
                };
                return Sectors;
            }
    
            public ObservableCollection<Pole> GetPoles()
            {
                var Poles = new ObservableCollection<Pole>()
                {
                    new Pole { Key = 1, Name = "Erdre et Cens", Color = "ffccd5"},
                    new Pole { Key = 2, Name = "Erdre et Loire", Color = "ff4d4d"},
                    new Pole { Key = 3, Name = "Loire-Sèvre et vignoble", Color = "ff9933"},
                    new Pole { Key = 4, Name = "Sud-Ouest", Color = "bfbfbf"},
                    new Pole { Key = 5, Name = "Loire-chézine", Color = "ffff4d"},
                    new Pole { Key = 6, Name = "Nantes-Ouest", Color = "3385ff"},
                    new Pole { Key = 7, Name = "Nantes-Loire", Color = "53c653"},
                };
                return Poles;
            }
    
            public void FindPoleName(string polename)
            {
                for (int search = 0; search < SectorsLists.Count(); search++)
                {
                    if (SectorsLists[search].PoleName == polename)
                    {
                        SectorsFindLists.Add(new Sector() {Key = search, Value = SectorsLists[search].Value, PoleName = polename });
                    }
                }
            }
    
            public string ShowBoxboard
            {
                get
                {
                    return $"{(_boxboard ? "Jour de collecte des cartons : oui " : "Jour de collecte des cartons : non")}";
                }
            }
    
            public string ShowGlass
            {
                get
                {
                    return $"{(_glass ? "Jour de collecte du verre : oui " : "Jour de collecte du verre : non")}";
                }
            }
    
            public string ShowHouseholdTrash
            {
                get
                {
                    return $"{(_householdTrash ? "Jour de collecte des Ordure ménagère : oui " : "Jour de collecte des Ordure ménagère : non")}";
                }
            }
        }
    
        public class Sector
        {
            private int _key;
            public int Key { get => _key; set => _key = value; }
    
            private string _value;
            public string Value { get => _value; set => _value = value; }
    
            private string _poleName;
            public string PoleName { get => _poleName; set => _poleName = value; }
        }
    
        public class Pole
        {
            private int _key;
            public int Key { get => _key; set => _key = value; }
    
            private string _color;
            public string Color { get => _color; set => _color = value; }
    
            private string _name;
            public string Name { get => _name; set => _name = value; }
        }
    }
    
  • TaylorDTaylorD USMember ✭✭✭

    When you set your BindingContext, you forgot to add the line below before you set it. You need to create an instance of your StatementReferencielPageModel in order to use it.

    _viewModel = new StatementReferencielPageModel(); // Add this line
    BindingContext = _viewModel;
    
  • camillecamille Member ✭✭

    pfff yes indeed in addition to being a beginner I am blind it will not help me much

    than she's making a mistake of inattention!

    but then with me I have another question that I hope will be the last one

    the list I get from my picker doesn't display the right elements it displays all the elements of my list Sectors of the group is better to store the new sectors of my find function in a new list?

  • TaylorDTaylorD USMember ✭✭✭

    I would suggest at the beginning of your FindPoleName function in your StatementReferencielPageModel, call SectorsFindLists.Clear() before your loop. Then when you add new elements, you will only have the Sector's for that polename.

  • camillecamille Member ✭✭
    edited January 28

    Yes, I had thought about it, but the same error as five minutes ago appears.

    Unhandled Exception:

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

  • TaylorDTaylorD USMember ✭✭✭

    You need to set your SectorsFindLists to a new list in your view model.

    StatementReferencielPageModel.cs

    private List<Sector> _sectorsFindLists = new List<Sector>();
    

    Or you can initialize it in the Constructor where you initialize your other lists.

  • camillecamille Member ✭✭

    I tried to fix my problem but in vain, unfortunately I still have my entire sector list which is displayed yet I empty it at the beginning of my function

    here is the part of the code I modified:

            public void FindPoleName(string polename)
            {
                var SectorsFindLists = new List<Sector>();
                SectorsFindLists.Clear();
                for (int search = 0; search < SectorsLists.Count(); search++)
                {
                    if (SectorsLists[search].PoleName == polename)
                    {
                        SectorsFindLists.Add(new Sector() { Key =search ,Value = SectorsLists[search].Value});
                    }
                }
            }
    
  • TaylorDTaylorD USMember ✭✭✭

    I would suggest looking at foreach loops when looping through a list. I'm not sure where the next issue is, but I'm guessing there is some logic that's wrong either in that loop or where some of the other lists are created with their items.

    Only the items that are getting added to your SectorsFindLists will be shown in the UI if the logic in the loop and such is set up correctly. Do some debugging with breakpoints and see which objects get added to your lists, and see if there is some wrong logic somewhere.

    Also, this line will create a big confusion to yourself and other readers of the code due to having the same variable name. It can cause unintended consequences also.

    var SectorsFindLists = new List<Sector>();
    

    While you need to initialize your list, don't create a new variable local to that function. Do it above your initial list declaration like I specified in the previous comment towards the top of your class.

  • camillecamille Member ✭✭
    edited January 30

    Hello TaylorD,

    so since the last message I posted I paused and later came back to my code and realized that there were some errors so I decided to review my code and change it.

    Now I can display my list well ( like what to take a break and go elsewhere can be useful).

    However I have a new problem that arises, when I want to scrub the selected item of my list it returns the object of my list but not its content (its variable).

    and about foreach, to be honest I never use it I always use the for loop is there really a big difference to what I use foreach?

    this is what it returns to me :

    and this is my code 2.0 :smile: : PolQual.ViewModel.Sector

    my vue : (only the picker to change)

                    <Picker
                        x:Name="PickerSectorsLists"
                        Title="Sélectionner votre secteur"
                        Grid.Row="2"
                        Grid.Column="1"
                        ItemDisplayBinding="{Binding Value}"
                        SelectedItem="{Binding Value}" />
    

    my code behind :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;
    using PolQual.ViewModels;
    
    namespace PolQual.Views
    {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class StatementReferencielPage : ContentPage
        {
            private StatementReferencielPageModel _srpm;
            private Button _polebutton;
    
            public StatementReferencielPageModel SRPM { get { return _srpm; } }
            public Button Polebutton { get => _polebutton; set => _polebutton = value; }
    
            public StatementReferencielPage()
            {
                _srpm = new StatementReferencielPageModel();
    
                InitializeComponent();
    
                BindingContext = _srpm;
    
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
                gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(40) });
    
                gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(25, GridUnitType.Star) });
                gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(50, GridUnitType.Star) });
                gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(25, GridUnitType.Star) });
    
                var PolesListsIndex = 0;
    
                for (int columnIndex = 1; columnIndex < 2; columnIndex++)
                {
                    for (int rowIndex = 0; rowIndex < 7; rowIndex++)
                    {
                        if (PolesListsIndex >= _srpm.PolesCollection.Count<Pole>())
                        {
                            return;
                        }
                        var poles = _srpm.PolesCollection[PolesListsIndex];
                        PolesListsIndex += 1;
    
                        Polebutton = new Button
                        {
                            Text = poles.Name,
                            BackgroundColor = Color.FromHex(poles.Color),
                            HorizontalOptions = LayoutOptions.Center,
                            VerticalOptions = LayoutOptions.Center,
                            WidthRequest = 280
                        };
                        string request = _srpm.PolesCollection[rowIndex].Name;
                        Polebutton.Clicked += delegate { SelectedPole(request); };// anonymous method
                        gridLayout.Children.Add(Polebutton, columnIndex, rowIndex);
    
                    }
                }
            }
    
            // Gestions Poles
    
            private void SelectedPole(string polename)
            {
                _srpm.FindPoleName(polename);
                bool result = _srpm.FindPoleName(polename);
    
                if (!result)
                {
                    PickerSectorsLists.ItemsSource = _srpm.SectorsFindLists.OrderBy(t => t.Key).ToList();
                    PickerSectorsLists.SelectedItem = _srpm.SectorsFindLists.OrderBy(t => t.Key).ToList();
                }
                else if (result)
                {
                    DisplayAlert("Erreur de recherche", "Impossible d'éffectué la recherche ", "D'accord");
                }
            }
    
            // Gestion de la Validation
    
            public void GoToAssesmentGrid(object sender, System.EventArgs e)
            {
                if (PickerSectorsLists.SelectedIndex == -1)
                {
                    DisplayAlert("Erreur de saisie", "Veuillez séléctioner un secteur svp! ", "D'accord");
                }
                else
                {
                    if(_srpm.AddPole() == true)
                    {
                        object essai1 = PickerSectorsLists.SelectedItem;
                        DisplayAlert("valeur choisit", "la valeur sélectionnée est :" + essai1, "D'accord");
                    }
    
                    if (_srpm.AddSector() == true)
                    {
                        PickerSectorsLists.ItemsSource = null;
                    }
                    var page = new AssesmentGridPage();
                   // Navigation.PushAsync(page);
                }
            }
        }
    }
    

    at last my viewModel :

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Text;
    using Xamarin.Forms;
    using PolQual.Views;
    using System.Collections.ObjectModel;
    
    namespace PolQual.ViewModels
    {
        public class StatementReferencielPageModel : INotifyPropertyChanged
        {
            private List<Sector> _sectorsLists;
            public List<Sector> SectorsLists { get => _sectorsLists; set => _sectorsLists = value; }
    
            private List<Sector> _sectorsFindLists;
            public List<Sector> SectorsFindLists { get => _sectorsFindLists; set => _sectorsFindLists = value; }
    
            private static ObservableCollection<Pole> _polesCollection;
            public ObservableCollection<Pole> PolesCollection { get => _polesCollection; set => _polesCollection = value; }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            public void OnPropertyChanged([CallerMemberName] string propertyname = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
    
            public StatementReferencielPageModel()
            {
                SectorsLists = GetSectors().OrderBy(t => t.Key).ToList();
                SectorsFindLists = new List<Sector>();
                PolesCollection = GetPoles();
            }
    
            public bool AddPole()
            {
                return true;
            }
    
            public bool AddSector()
            {
                return true;
            }
    
            public bool FindPoleName(string polename)
            {
                int SizeListBefore = SectorsFindLists.Count();
                SectorsFindLists.Clear();
                for (int search = 0; search < SectorsLists.Count(); search++)
                {
                    if (SectorsLists[search].PoleName == polename)
                    {
                        SectorsFindLists.Add(new Sector() { Value = SectorsLists[search].Value });
                    }
                }
                int SizeListAfter = SectorsFindLists.Count();
                return SizeListBefore > SizeListAfter;
            }
    
            private bool _boxboard { get; set; }
            public bool Boxboard
            {
                get { return _boxboard; }
                set
                {
                    _boxboard = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(ShowBoxboard));
                }
            }
    
            private bool _glass { get; set; }
            public bool Glass
            {
                get { return _glass; }
                set
                {
                    _glass = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(ShowGlass));
                }
            }
    
            private bool _householdTrash { get; set; }
            public bool HouseholdTrash
            {
                get { return _householdTrash; }
                set
                {
                    _householdTrash = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(ShowHouseholdTrash));
                }
            }
    
            private Sector _selectedSector { get; set; }
            public Sector SelectedSector
            {
                get { return _selectedSector; }
                set
                {
                    if (_selectedSector != value)
                    {
                        _selectedSector = value;
                        // que faire quand l'élèment est sélectionné !
                    }
                }
            }
    
            public string ShowBoxboard
            {
                get
                {
                    return $"{(_boxboard ? "Jour de collecte des cartons : oui " : "Jour de collecte des cartons : non")}";
                }
            }
    
            public string ShowGlass
            {
                get
                {
                    return $"{(_glass ? "Jour de collecte du verre : oui " : "Jour de collecte du verre : non")}";
                }
            }
    
            public string ShowHouseholdTrash
            {
                get
                {
                    return $"{(_householdTrash ? "Jour de collecte des Ordure ménagère : oui " : "Jour de collecte des Ordure ménagère : non")}";
                }
            }
    
            public List<Sector> GetSectors()
            {
                var Sectors = new List<Sector>()
                {
                    //Erdre et cens
                    new Sector() { Key = 0, Value = "Sautron", PoleName="Erdre et cens" },
                    new Sector() { Key = 1, Value = "Orvault", PoleName="Erdre et cens" },
                    new Sector() { Key = 2, Value = "Nantes Nord", PoleName="Erdre et cens" },
                    new Sector() { Key = 3, Value = "La-Chapelle-Sur-Erdre", PoleName="Erdre et cens" },
                    // Erdre et Loire
                    new Sector() { Key = 4, Value = "Mauves-Sur-Loire", PoleName="Erdre et Loire" },
                    new Sector() { Key = 5, Value = "Carquefou", PoleName="Erdre et Loire" },
                    new Sector() { Key = 6, Value = "Thouré sur Loire", PoleName="Erdre et Loire" },
                    new Sector() { Key = 7, Value = "Sainte Luce sur Loire", PoleName="Erdre et Loire" },
                    new Sector() { Key = 8, Value = "Nantes Erdre", PoleName="Erdre et Loire" },
                    new Sector() { Key = 9, Value = "Doulon", PoleName="Erdre et Loire" },
                    //Loire-Sèvre et Vignoble
                    new Sector() { Key = 10, Value = "Rezé", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 11, Value = "Les Sornières", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 12, Value = "Vertou", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 13, Value = "Saint Sébastien sur Loire", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 14, Value = "Base Goulaine", PoleName="Loire-Sèvre et Vignoble" },
                    new Sector() { Key = 15, Value = "Nantes sud", PoleName="Loire-Sèvre et Vignoble" },
                    //Sud-Ouest
                    new Sector() { Key = 16, Value = "Bouchenais", PoleName="Sud-Ouest" },
                    new Sector() { Key = 17, Value = "Saint-Aignan-Grandlieu", PoleName="Sud-Ouest" },
                    new Sector() { Key = 18, Value = "Bouaye", PoleName="Sud-Ouest" },
                    new Sector() { Key = 19, Value = "Saint-Leger-Les-Vignes", PoleName="Sud-Ouest" },
                    new Sector() { Key = 20, Value = "Brains", PoleName="Sud-Ouest" },
                    new Sector() { Key = 21, Value = "La-Montagne", PoleName="Sud-Ouest" },
                    new Sector() { Key = 22, Value = "Saint-Jean-De-Boiseau", PoleName="Sud-Ouest" },
                    new Sector() { Key = 23, Value = "Le Pellerin", PoleName="Sud-Ouest" },
                    //Loire-Chézine
                    new Sector() { Key = 24, Value = "Couëron", PoleName="Loire-Chézine" },
                    new Sector() { Key = 25, Value = "Saint-Herblain", PoleName="Loire-Chézine" },
                    new Sector() { Key = 26, Value = "Indre", PoleName="Loire-Chézine" },
                    //Nantes-Ouest
                    new Sector() { Key = 27, Value = "Bellevue-Chantenay-Sainte-Anne", PoleName="Nantes-Ouest" },
                    new Sector() { Key = 28, Value = "Dervallière-Zola", PoleName="Nantes-Ouest" },
                    new Sector() { Key = 29, Value = "Breil-Barberie", PoleName="Nantes-Ouest" },
                    new Sector() { Key = 30, Value = "Hauts Pavés Saint Félix", PoleName="Nantes-Ouest" },
                    //Nantes-Loire
                    new Sector() { Key = 31, Value = "Malakof-Saint-Donatien", PoleName="Nantes-Loire" },
                    new Sector() { Key = 32, Value = "Centre Ville", PoleName="Nantes-Loire" },
                    new Sector() { Key = 33, Value = "île de Nantes", PoleName="Nantes-Loire" },
    
                };
                return Sectors;
            }
    
            public ObservableCollection<Pole> GetPoles()
            {
                var Poles = new ObservableCollection<Pole>()
                {
                    new Pole { Key = 0, Name = "Erdre et cens", Color = "ffccd5"},
                    new Pole { Key = 1, Name = "Erdre et Loire", Color = "ff4d4d"},
                    new Pole { Key = 2, Name = "Loire-Sèvre et Vignoble", Color = "ff9933"},
                    new Pole { Key = 3, Name = "Sud-Ouest", Color = "bfbfbf"},
                    new Pole { Key = 4, Name = "Loire-Chézine", Color = "ffff4d"},
                    new Pole { Key = 5, Name = "Nantes-Ouest", Color = "3385ff"},
                    new Pole { Key = 6, Name = "Nantes-Loire", Color = "53c653"},
                };
                return Poles;
            }
        }
    
        public class Sector
        {
            private int _key;
            public int Key { get => _key; set => _key = value; }
    
            private string _value;
            public string Value { get => _value; set => _value = value; }
    
            private string _poleName;
            public string PoleName { get => _poleName; set => _poleName = value; }
        }
    
        public class Pole
        {
            private int _key;
            public int Key { get => _key; set => _key = value; }
    
            private string _color;
            public string Color { get => _color; set => _color = value; }
    
            private string _name;
            public string Name { get => _name; set => _name = value; }
        }
    }
    
  • camillecamille Member ✭✭

    I have found a way to recover the value of the selected sector using this method:

            private string SelectedSector()
            {
                int SectorIndex = PickerSectorsLists.SelectedIndex;
                string SectorName = _srpm.SectorsFindLists[SectorIndex].Value;
    
                return SectorName;
            }
    

    I want to know if it's okay to do it like this or not?
    In any case, I thank you for your help. You have been very useful to me :smile:

  • TaylorDTaylorD USMember ✭✭✭

    Xamarin.Forms Picker has a SelectedItem property and you should use that. That should return your specified object if your Picker is binded to the appropriate list SectorsFindLists from your ViewModel

    if (PickerSectorsLists.SelectedItem is Sector sector)
    {
        // Do what you want with the sector here
    }
    

    OR
    Since your Picker is binded to the SelectedSector in your ViewModel, that will update when a value is selected in your PickerSectorsLists. Then in the setter of the property in you ViewModel, do you logic for your selected item there.

  • camillecamille Member ✭✭
    edited January 31

    All right, it works, so I replaced my previous function with this in my behind code:

            private bool SelectedSector()
            {
                if (PickerSectorsLists.SelectedItem is Sector sector)
                {
                    string result = sector.Value;
                    _srpm.Sectorselected(result);
                    return true;
                }else
                {
                    return false;
                }
            }
    

    then in my view model I created a method that will store the result and then transmit it in the data base (but for the moment I don't care about it)

            public string Sectorselected(string item)
            {
                return item;
            }
    
Sign In or Register to comment.