question

Grime avatar image
0 Votes"
Grime asked LeonLu-MSFT commented

How to Use the MVVM Architectural Pattern to Pass Data (both Push and Pop) Between Pages

I'm writing an app where I need to perform CRUD operations on a list of people, called "Operators". Each Operator has a unique ID, a name, a phone number, an email address and an avatar.
With the help of @JessieZhang-2116, I am able to select a particular Operator from my SelectOperatorPage, then return this to my OperatorsPage.
From here, though, I wish to be able to Update the details of that Operator by pushing to a new OperatorInfoPage. This page should be able to be used for editing or deleting existing Operators or adding new Operators.

My problem is how to set Bindings so that data can be read from the OperatorInfoPage and the NewOperatorPage, and potentially how to delete the currently selected Operator.

The Pages, their code behinds and the Model and ViewModel classes are presented here...

OperatorModel.cs

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Runtime.CompilerServices;
 using System.Text;
 using SQLite;
    
 namespace HandsFreeNotes.Model
 {
     //    public class OperatorModel
     // The line above changed to the line below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
     public class OperatorModel: INotifyPropertyChanged
     {
         public int OperatorID { get; set; }
         //        public string OperatorName { get; set; }
         // The 1 line above changed to the 6 lines below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
         string _operatorName;
         public string OperatorName
         {
             set { SetProperty(ref _operatorName, value); }
             get { return _operatorName; }
         }
    
         public string OperatorPhone { get; set; }
         public string OperatorEmail { get; set; }
         public string OperatorAvatar { get; set; }
    
         // The 4 lines below added at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
         public OperatorModel()
         {
    
         }
    
         public OperatorModel(int operatorID, string operatorName, string operatorPhone, string operatorEmail, string operatorAvatar)
         {
             OperatorID = operatorID;
             OperatorName = operatorName;
             OperatorPhone = operatorPhone;
             OperatorEmail = operatorEmail;
             OperatorAvatar = operatorAvatar;
         }
         // All the lines below added at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
         bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
         {
             if (Object.Equals(storage, value))
                 return false;
    
             storage = value;
             OnPropertyChanged(propertyName);
             return true;
         }
         protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
         {
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
         }
    
         public event PropertyChangedEventHandler PropertyChanged;
     }
    
    
 }

OperatorViewModel.cs

 using HandsFreeNotes.Model;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Text;
 using System.Threading.Tasks;
 using Xamarin.Forms;
    
 namespace HandsFreeNotes.ViewModel
 {
     public class OperatorViewModel : INotifyPropertyChanged
     {
         private string _HFNName;
    
         public string HFNName
         {
             get
             {
                 return _HFNName;
             }
                
             set
             {
                 _HFNName = value;
                 RaisePropertyChanged("HFNName");
             }
         }
    
         public List<OperatorModel> OperatorList;
         public OperatorModel SelectedOperator;
    
         public async Task<bool> GetOperators()
         {
             if (OperatorList == null)
             {
                 OperatorList = new List<OperatorModel>();
                 OperatorList.Add(new OperatorModel(1, "Grime", "+61419659866", "apps@grime.net", "gs300.png"));
                 OperatorList.Add(new OperatorModel(2, "Brookey", "+61419659866", "brookey@grime.net", "gmb.jpg"));
                 OperatorList.Add(new OperatorModel(3, "CC", "+61422192456", "shaunachick@gmail.com", "cc.jpg"));
                 OperatorList.Add(new OperatorModel(4, "Monte", "+61412595878", "monte@aussieweb.com.au", "monte2a.jpg"));
                 OperatorList.Add(new OperatorModel(5, "Jeff", "+61409998197", "jeff@content2convert.com.au", "jeff.jpg"));
             }
    
             return true;
         }
    
         public event PropertyChangedEventHandler PropertyChanged;
    
         protected void RaisePropertyChanged(string prop)
         {
             if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
         }
    
         public bool UpdateOperator(OperatorModel opm)
         {
             SelectedOperator.OperatorName = opm.OperatorName;
             SelectedOperator.OperatorPhone = opm.OperatorPhone;
             SelectedOperator.OperatorEmail = opm.OperatorEmail;
             SelectedOperator.OperatorAvatar = opm.OperatorAvatar;
    
             return true;
         }
     }
 }

OperatorsPage.xaml

 <?xml version="1.0" encoding="utf-8" ?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="HandsFreeNotes.View.OperatorsPage">
     <ContentPage.Content>
         <Grid BackgroundColor="White">
             <Grid.RowDefinitions>
                 <RowDefinition Height="40"/>
                 <RowDefinition Height="40"/>
                 <RowDefinition Height="40"/>
                 <RowDefinition Height="70"/>
                 <RowDefinition Height="*"/>
                 <RowDefinition Height="50"/>
             </Grid.RowDefinitions>
    
             <Grid.ColumnDefinitions>
                 <ColumnDefinition Width="50"/>
                 <ColumnDefinition Width="*"/>
                 <ColumnDefinition Width="50"/>
             </Grid.ColumnDefinitions>
    
             <Button
                 x:Name="BackButton"
                 Text="Back"
                 Grid.Row="0"
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 TextColor="Black"
                 FontAttributes="Bold"
                 HeightRequest="40"
                 VerticalOptions="Center"
                 HorizontalOptions="End"
                 Margin="0,0,20,0"
                 Clicked="BackButton_Clicked"/>
    
             <Image 
                 Source="hfn256"
                 Margin="2"
                 Grid.Row="1" 
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 HorizontalOptions="Center"
                 BackgroundColor="Transparent"/>
    
             <Label 
                 Text="Operator"
                 FontSize="Large"
                 TextColor="Black"
                 FontAttributes="Bold"
                 Margin =" 0, 0, 0, 0"
                 Grid.Row="2" 
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 HorizontalOptions="Center"
                 VerticalOptions="End"
                 BackgroundColor="Transparent"/>
    
             <StackLayout
                 Grid.Row="3" 
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 Orientation="Horizontal">
    
                 <Label
                     Text="Selected Operator: "
                     TextColor="Black"
                     FontSize="Medium"
                     FontAttributes="Bold"
                     HorizontalOptions="End"
                     VerticalOptions="Center"
                     BackgroundColor="Transparent"
                     Margin="20, 0, 0, 0"
                     WidthRequest="200"/>
    
                 <Entry 
                 x:Name="SelectedOperatorEntry"
                 Text="{Binding OperatorName}"
                 TextColor="Green"
                 IsReadOnly="True"
                 Placeholder="No Currently Selected Operator"
                 PlaceholderColor="LightGray"
                 FontSize="Medium"
                 FontAttributes="Italic"
                 Margin ="0, 0, 0, 0"
                 HorizontalOptions="Center"
                 VerticalOptions="Center"
                 BackgroundColor="Transparent"
                 WidthRequest="200"/>
    
             </StackLayout>
    
             <ScrollView 
                 Orientation="Vertical"
                 Grid.Row="4" 
                 Grid.Column="0"
                 Grid.ColumnSpan="3">
                 <Grid BackgroundColor="White" >
                     <Grid.RowDefinitions>
                         <RowDefinition Height="50"/>
                         <RowDefinition Height="50"/>
                         <RowDefinition Height="50"/>
                         <RowDefinition Height="100"/>
                         <RowDefinition Height="20"/>
                     </Grid.RowDefinitions>
    
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition Width="50"/>
                         <ColumnDefinition Width="*"/>
                         <ColumnDefinition Width="50"/>
                     </Grid.ColumnDefinitions>
    
                     <Button
                         x:Name="SelectOperatorButton"
                         Text="Select Operator"
                         FontSize="Medium"
                         Grid.Row="0"
                         Grid.Column="1"
                         TextColor="Black"
                         FontAttributes="Bold"
                         BackgroundColor="White"
                         Margin="0,0,0,0"
                         HorizontalOptions="Center"
                         VerticalOptions="Start"
                         Clicked="SelectOperatorButton_Clicked"/>
    
                     <Button
                         x:Name="UpdateOperatorButton"
                         Text="Update Selected Operator"
                         FontSize="Medium"
                         Grid.Row="1"
                         Grid.Column="1"
                         TextColor="Black"
                         FontAttributes="Bold"
                         BackgroundColor="White"
                         Margin="0,0,0,0"
                         HorizontalOptions="Center"
                         VerticalOptions="Start"
                         Clicked="UpdateOperatorButton_Clicked"/>
    
                     <Button
                         x:Name="DeleteOperatorButton"
                         Text="Delete Selected Operator"
                         FontSize="Medium"
                         Grid.Row="2"
                         Grid.Column="1"
                         TextColor="Black"
                         FontAttributes="Bold"
                         BackgroundColor="White"
                         Margin="0,0,0,0"
                         HorizontalOptions="Center"
                         VerticalOptions="Start"/>
    
                     <Button
                         x:Name="AddOperatorButton"
                         Text="Add New Operator"
                         FontSize="Medium"
                         Grid.Row="3"
                         Grid.Column="1"
                         HorizontalOptions="Center"
                         VerticalOptions="End"
                         TextColor="Black"
                         FontAttributes="Bold"
                         BackgroundColor="White"
                         Margin="0,0,0,0"
                         Clicked="AddOperatorButton_Clicked"/>
    
                 </Grid>
    
             </ScrollView>
    
         </Grid>
     </ContentPage.Content>
 </ContentPage>

OperatorsPage.xaml.cs

 using HandsFreeNotes.ViewModel;
 using HandsFreeNotes.Model;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
    
 using Xamarin.Forms;
 using Xamarin.Forms.Xaml;
    
 namespace HandsFreeNotes.View
 {
     [XamlCompilation(XamlCompilationOptions.Compile)]
    
     public partial class OperatorsPage : ContentPage
     {
         OperatorViewModel ovm;
         OperatorModel opm;
    
         // public OperatorsPage(OperatorViewModel _ovm)
         // The line above changed to the line below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
         public OperatorsPage()
         {
             // add a bit of padding to cater to the "notch" on the iPhone.
             if (Device.RuntimePlatform == Device.iOS)
             {
                 Padding = new Thickness(0, 40, 0, 0);
             }
    
             InitializeComponent();
    
             // ovm = _ovm;
             // opm = ovm.SelectedOperator;
             // The 2 lines above changed to the line below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
             opm = new OperatorModel();
    
             BindingContext = opm;
    
         }
    
         private async void BackButton_Clicked(object sender, EventArgs e)
         {
             await Navigation.PopModalAsync();
             // The line above originally commented out at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
         }
    
         private async void AddOperatorButton_Clicked(object sender, EventArgs e)
         {
             await Navigation.PushModalAsync(new NewOperatorPage());
             // The line above originally commented out at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
    
         }
    
         private async void SelectOperatorButton_Clicked(object sender, EventArgs e)
         {
             // The lines below added at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
             SelectOperatorPage page = new SelectOperatorPage();
             page.ReturnValue += delegate (object s, OperatorModel operatorModel)
             {
                 BackCall(s, operatorModel);
             };
    
             await Navigation.PushModalAsync(page);
         }
         // The lines below added at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
         private void BackCall(object s, OperatorModel model)
         {
             opm.OperatorName = model.OperatorName;
         }
    
         private async void UpdateOperatorButton_Clicked(object sender, EventArgs e)
         {
             //var operatorInfoPage = new OperatorInfoPage();
             //operatorInfoPage.BindingContext = ovm;
             //await Navigation.PushModalAsync(operatorInfoPage);
    
         }
     }
 }

SelectOperatorPage.xaml

 <?xml version="1.0" encoding="utf-8" ?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="HandsFreeNotes.View.SelectOperatorPage">
    
     <ContentPage.Content>
         <Grid BackgroundColor="White">
             <Grid.RowDefinitions>
                 <RowDefinition Height="40"/>
                 <RowDefinition Height="40"/>
                 <RowDefinition Height="80"/>
                 <RowDefinition Height="*"/>
                 <RowDefinition Height="50"/>
             </Grid.RowDefinitions>
    
             <Grid.ColumnDefinitions>
                 <ColumnDefinition Width="50"/>
                 <ColumnDefinition Width="*"/>
                 <ColumnDefinition Width="50"/>
             </Grid.ColumnDefinitions>
    
             <Button
                 x:Name="BackButton"
                 Text="Back"
                 Grid.Row="0"
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 TextColor="Black"
                 FontAttributes="Bold"
                 HeightRequest="40"
                 VerticalOptions="CenterAndExpand"
                 HorizontalOptions="End"
                 Margin="0,0,20,0"
                 Clicked="BackButton_Clicked"/>
    
             <Image 
                 Source="hfn256"
                 Margin="2"
                 Grid.Row="1" 
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 HorizontalOptions="Center"
                 BackgroundColor="Transparent"/>
    
             <Label 
                 Text="Select Operator..."
                 FontSize="Large"
                 TextColor="Black"
                 FontAttributes="Bold"
                 Grid.Row="2" 
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 HorizontalOptions="Center"
                 VerticalOptions="Start"
                 Margin="20"
                 BackgroundColor="Transparent"/>
    
             <ListView
                 x:Name="OperatorListView"
                 Grid.Row="3"
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 RowHeight="140"
                 ItemSelected="OperatorListView_ItemSelected">
                 <ListView.ItemTemplate>
                     <DataTemplate>
                         <ViewCell>
                             <ContentView>
                                 <Grid>
                                     <Grid.RowDefinitions>
                                         <RowDefinition Height="*"/>
                                     </Grid.RowDefinitions>
                                     <Grid.ColumnDefinitions>
                                         <ColumnDefinition Width="100"/>
                                         <ColumnDefinition Width="100"/>
                                         <ColumnDefinition Width="200"/>
                                     </Grid.ColumnDefinitions>
    
                                     <Image
                                         Source="{Binding OperatorAvatar}"
                                         Grid.Row="0"
                                         Grid.Column="0"
                                         HeightRequest="200"
                                         WidthRequest="100"/>
    
                                     <Label
                                         Text="{Binding OperatorName}"
                                         FontAttributes="Bold"
                                         HorizontalOptions="Start"
                                         VerticalOptions="Center"
                                         Grid.Row ="0"
                                         Grid.Column="1"/>
    
                                     <Label
                                         Text="{Binding OperatorEmail}"
                                         FontAttributes="Italic"
                                         FontSize="Micro"
                                         Grid.Row="0"
                                         Grid.Column="2"
                                         HeightRequest="30"
                                         HorizontalOptions="Start"
                                         VerticalOptions="Center"/>
    
                                     <Label
                                         Text="{Binding OperatorPhone}"
                                         FontAttributes="Italic"
                                         FontSize="Small"
                                         Grid.Row="0"
                                         Grid.Column="2"
                                         HeightRequest="30"
                                         HorizontalOptions="Start"
                                         VerticalOptions="End"/>
    
                                 </Grid>
                             </ContentView>
                         </ViewCell>
                     </DataTemplate>
                 </ListView.ItemTemplate>
             </ListView>
    
         </Grid>
     </ContentPage.Content>
 </ContentPage>

SelectOperatorPage.xaml.cs

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
    
 using Xamarin.Forms;
 using Xamarin.Forms.Xaml;
 using HandsFreeNotes.ViewModel;
 using HandsFreeNotes.Model;
    
 namespace HandsFreeNotes.View
 {
     [XamlCompilation(XamlCompilationOptions.Compile)]
     public partial class SelectOperatorPage : ContentPage
     {
         OperatorViewModel ovm;
    
         // Added the line below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
         public EventHandler<OperatorModel> ReturnValue;
    
         public SelectOperatorPage()
         {
             // add a bit of padding to cater to the "notch" on the iPhone.
             if (Device.RuntimePlatform == Device.iOS)
             {
                 Padding = new Thickness(0, 40, 0, 0);
             }
    
             InitializeComponent();
    
             ovm = new OperatorViewModel();
    
             BindingContext = ovm;
         }
    
         protected override async void OnAppearing()
         {
             base.OnAppearing();
             await ovm.GetOperators();
             OperatorListView.ItemsSource = ovm.OperatorList;
         }
    
         private async void BackButton_Clicked(object sender, EventArgs e)
         {
             await Navigation.PopModalAsync();
         }
    
         private async void OperatorListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
         {
             if (e.SelectedItem != null)
             {
                 // Typecast the e.SelectedItem object to an OperatorModel
    
                 // ovm.SelectedOperator = (OperatorModel)e.SelectedItem;
                 // await DisplayAlert("Alert", "Selected Operator: " + ovm.SelectedOperator.OperatorName, "Exit");
    
                 // The 2 lines above were changed to the 7 below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
    
                 OperatorModel operatorModel = (OperatorModel)e.SelectedItem;
                 ovm.SelectedOperator = operatorModel;
                 EventHandler<OperatorModel> handler = ReturnValue;
                 if (handler != null)
                 {
                     handler(this, operatorModel);
                 }
    
    
                 await Navigation.PopModalAsync();
             }
         }
     }
 }

OperatorInfoPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="HandsFreeNotes.View.OperatorInfoPage">
<ContentPage.Content>
<Grid BackgroundColor="White">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="30"/>
<RowDefinition Height="10"/>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>

         <Grid.ColumnDefinitions>
             <ColumnDefinition Width="50"/>
             <ColumnDefinition Width="*"/>
             <ColumnDefinition Width="50"/>
         </Grid.ColumnDefinitions>

         <Button
             x:Name="BackButton"
             Text="Back"
             Grid.Row="0"
             Grid.Column="0"
             Grid.ColumnSpan="3"
             TextColor="Black"
             FontAttributes="Bold"
             HeightRequest="40"
             VerticalOptions="CenterAndExpand"
             HorizontalOptions="End"
             Margin="0,0,20,0"
             Clicked="BackButton_Clicked"/>

         <Image 
             Source="hfn256"
             Margin="2"
             Grid.Row="1" 
             Grid.Column="0"
             Grid.ColumnSpan="3"
             HorizontalOptions="Center"
             BackgroundColor="Transparent"/>

         <Label 
             Text="Update Operator"
             FontSize="Large"
             TextColor="Black"
             FontAttributes="Bold"
             Padding =" 0, 0, 0, 0"
             Grid.Row="2" 
             Grid.Column="0"
             Grid.ColumnSpan="3"
             HorizontalOptions="Center"
             VerticalOptions="End"
             BackgroundColor="Transparent"/>

         <ScrollView Orientation="Vertical"
         Grid.Row="4" Grid.Column="0"
         Grid.ColumnSpan="3">
             <Grid BackgroundColor="White" >
                 <Grid.RowDefinitions>
                     <RowDefinition Height="60"/>
                     <RowDefinition Height="50"/>
                     <RowDefinition Height="50"/>
                     <RowDefinition Height="50"/>
                     <RowDefinition Height="100"/>
                     <RowDefinition Height="50"/>
                 </Grid.RowDefinitions>

                 <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="Auto"/>
                     <ColumnDefinition Width="80"/>
                     <ColumnDefinition Width="*"/>
                 </Grid.ColumnDefinitions>

                 <Label
                     x:Name="NameLabel"
                     Text="Name: "
                     TextColor="Black"
                     FontSize="Medium"
                     FontAttributes="Bold"
                     Grid.Row="0"
                     Margin="40, 0, 0, 0"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"/>

                 <Entry
                     x:Name="NameEntry"
                     Text="{Binding OperatorName}"
                     Placeholder="Enter a name / callsign"
                     PlaceholderColor="LightGray"
                     TextColor="DarkBlue"
                     FontSize="Medium"
                     Keyboard="Plain"
                     Grid.Row="0"
                     Grid.Column="1"
                     Grid.ColumnSpan="2"
                     Margin="0, 0, 30, 0"/>

                 <Label
                     x:Name="PhoneLabel"
                     Text="Phone:    +"
                     TextColor="Black"
                     FontSize="Medium"
                     FontAttributes="Bold"
                     Grid.Row="1"
                     Grid.Column="0"
                     Margin="40, 0, 0, 0"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"/>

<!-- <Entry
x:Name="PhoneCountryEntry"
Text="{Binding }"
Placeholder="Country"
PlaceholderColor="LightGray"
TextColor="DarkBlue"
FontSize="Medium"
Keyboard="Numeric"
Grid.Row="1"
Grid.Column="1"
Margin="0, 0, 0, 0"/> -->

                 <Entry
                     x:Name="PhoneEntry"
                     Text="{Binding OperatorPhone}"
                     Placeholder="Phone (inc. Country - no spaces)"
                     PlaceholderColor="LightGray"
                     TextColor="DarkBlue"
                     FontSize="Medium"
                     Keyboard="Numeric"
                     Grid.Row="1"
                     Grid.Column="1"
                     Grid.ColumnSpan="2"
                     Margin="0, 0, 30, 0"/>

                 <Label
                     x:Name="EmailLabel"
                     Text="Email: "
                     TextColor="Black"
                     FontSize="Medium"
                     FontAttributes="Bold"
                     Grid.Row="2"
                     Margin="40, 0, 0, 0"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"/>

                 <Entry
                     x:Name="EmailEntry"
                     Text="{Binding OperatorEmail}"
                     Placeholder="Enter Email..."
                     PlaceholderColor="LightGray"
                     TextColor="DarkBlue"
                     FontSize="Medium"
                     Keyboard="Email"
                     Grid.Row="2"
                     Grid.Column="1"
                     Grid.ColumnSpan="2"
                     Margin="0, 0, 30, 0"/>

                 <Label
                     x:Name="AvatarLabel"
                     Text="Avatar: "
                     TextColor="Black"
                     FontSize="Medium"
                     FontAttributes="Bold"
                     Grid.Row="3"
                     Margin="40, 0, 0, 0"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"/>

                 <Entry
                     x:Name="AvatarEntry"
                     Text="{Binding OperatorAvatar}"
                     Placeholder="Enter Avatar URL..."
                     PlaceholderColor="LightGray"
                     TextColor="DarkBlue"
                     FontSize="Medium"
                     Keyboard="Plain"
                     Grid.Row="3"
                     Grid.Column="1"
                     Grid.ColumnSpan="2"
                     Margin="0, 0, 30, 0"/>

                 <Button
                     x:Name="OKButton"
                     Text="OK"
                     TextColor="Black"
                     FontAttributes="Bold"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"
                     WidthRequest="100"
                     HeightRequest="40"
                     Margin="0, 20, 0, 0"
                     Grid.Row="4"
                     Grid.Column="1"
                     Clicked="OKButton_Clicked"/>

                 <Button
                     x:Name="CancelButton"
                     Text="Cancel"
                     TextColor="Black"
                     FontAttributes="Bold"
                     HorizontalOptions="End"
                     VerticalOptions="Center"
                     WidthRequest="100"
                     HeightRequest="40"
                     Margin="0, 20, 40, 0"
                     Grid.Row="4"
                     Grid.Column="2"
                     Clicked="CancelButton_Clicked"/>

             </Grid>
         </ScrollView>
     </Grid>
 </ContentPage.Content>

</ContentPage>

OperatorInfoPage.xaml.cs

 using HandsFreeNotes.Model;
 using HandsFreeNotes.ViewModel;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
    
 using Xamarin.Forms;
 using Xamarin.Forms.Xaml;
    
 namespace HandsFreeNotes.View
 {
     [XamlCompilation(XamlCompilationOptions.Compile)]
     public partial class OperatorInfoPage : ContentPage
     {
         OperatorViewModel ovm;
         OperatorModel opm;
    
         public OperatorInfoPage(OperatorViewModel _ovm)
         {
             // add a bit of padding to cater to the "notch" on the iPhone.
             if (Device.RuntimePlatform == Device.iOS)
             {
                 Padding = new Thickness(0, 40, 0, 0);
             }
    
             InitializeComponent();
    
             ovm = _ovm;
             opm = ovm.SelectedOperator;
    
             BindingContext = opm; 
         }
    
         private async void BackButton_Clicked(object sender, EventArgs e)
         {
             await Navigation.PopModalAsync();
         }
    
         private async void OKButton_Clicked(object sender, EventArgs e)
         {
             await Navigation.PopModalAsync();
         }
    
         private async void CancelButton_Clicked(object sender, EventArgs e)
         {
             await Navigation.PopModalAsync();
         }
     }
 }



dotnet-csharpdotnet-xamarin
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

LeonLu-MSFT avatar image
0 Votes"
LeonLu-MSFT answered Grime commented

That leaves Edit/Update Operator. Currently, the updateOperatorButton_Clicked does nothing...

Please copy following code in UpdateOperatorButton_Clicked method of OperatorsPage.xaml.cs

private async void UpdateOperatorButton_Clicked(object sender, EventArgs e)
        {

            if (SelectModel != null)
            {

                  var operatorInfoPage = new OperatorInfoPage(SelectModel);
                operatorInfoPage.ReturnValue += delegate (object s, OperatorModel operatorModel)
                {
                    BackCall(s, operatorModel);
                };
                await Navigation.PushModalAsync(operatorInfoPage);
            }
            else
            {
                await DisplayAlert("info", "please select item", "OK");
            }

        }


Here is code about OperatorInfoPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App94.OperatorInfoPage">
    <ContentPage.Content>
        <Grid BackgroundColor="White">
            <Grid.RowDefinitions>
                <RowDefinition Height="40"/>
                <RowDefinition Height="40"/>
                <RowDefinition Height="30"/>
                <RowDefinition Height="10"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="50"/>
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="50"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="50"/>
            </Grid.ColumnDefinitions>
            <Button
             x:Name="BackButton"
             Text="Back"
             Grid.Row="0"
             Grid.Column="0"
             Grid.ColumnSpan="3"
             TextColor="Black"
             FontAttributes="Bold"
             HeightRequest="40"
             VerticalOptions="CenterAndExpand"
             HorizontalOptions="End"
             Margin="0,0,20,0"
             Clicked="BackButton_Clicked"/>
            <Image 
             Source="hfn256"
             Margin="2"
             Grid.Row="1" 
             Grid.Column="0"
             Grid.ColumnSpan="3"
             HorizontalOptions="Center"
             BackgroundColor="Transparent"/>
            <Label 
             Text="Update Operator"
             FontSize="Large"
             TextColor="Black"
             FontAttributes="Bold"
             Padding =" 0, 0, 0, 0"
             Grid.Row="2" 
             Grid.Column="0"
             Grid.ColumnSpan="3"
             HorizontalOptions="Center"
             VerticalOptions="End"
             BackgroundColor="Transparent"/>
            <ScrollView Orientation="Vertical"
         Grid.Row="4" Grid.Column="0"
         Grid.ColumnSpan="3">
                <Grid BackgroundColor="White" >
                    <Grid.RowDefinitions>
                        <RowDefinition Height="60"/>
                        <RowDefinition Height="50"/>
                        <RowDefinition Height="50"/>
                        <RowDefinition Height="50"/>
                        <RowDefinition Height="100"/>
                        <RowDefinition Height="50"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="80"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Label
                     x:Name="NameLabel"
                     Text="Name: "
                     TextColor="Black"
                     FontSize="Medium"
                     FontAttributes="Bold"
                     Grid.Row="0"
                     Margin="40, 0, 0, 0"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"/>
                    <Entry
                     x:Name="NameEntry"
                     Text="{Binding opm1.OperatorName}"
                     Placeholder="Enter a name / callsign"
                     PlaceholderColor="LightGray"
                     TextColor="DarkBlue"
                     FontSize="Medium"
                     Keyboard="Plain"
                     Grid.Row="0"
                     Grid.Column="1"
                     Grid.ColumnSpan="2"
                     Margin="0, 0, 30, 0"/>
                    <Label
                     x:Name="PhoneLabel"
                     Text="Phone:    +"
                     TextColor="Black"
                     FontSize="Medium"
                     FontAttributes="Bold"
                     Grid.Row="1"
                     Grid.Column="0"
                     Margin="40, 0, 0, 0"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"/>

                    <!-- <Entry
x:Name="PhoneCountryEntry"
Text="{Binding }"
Placeholder="Country"
PlaceholderColor="LightGray"
TextColor="DarkBlue"
FontSize="Medium"
Keyboard="Numeric"
Grid.Row="1"
Grid.Column="1"
Margin="0, 0, 0, 0"/> -->

                    <Entry
                     x:Name="PhoneEntry"
                     Text="{Binding opm1.OperatorPhone}"
                     Placeholder="Phone (inc. Country - no spaces)"
                     PlaceholderColor="LightGray"
                     TextColor="DarkBlue"
                     FontSize="Medium"
                     Keyboard="Numeric"
                     Grid.Row="1"
                     Grid.Column="1"
                     Grid.ColumnSpan="2"
                     Margin="0, 0, 30, 0"/>
                    <Label
                     x:Name="EmailLabel"
                     Text="Email: "
                     TextColor="Black"
                     FontSize="Medium"
                     FontAttributes="Bold"
                     Grid.Row="2"
                     Margin="40, 0, 0, 0"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"/>
                    <Entry
                     x:Name="EmailEntry"
                     Text="{Binding opm1.OperatorEmail}"
                     Placeholder="Enter Email..."
                     PlaceholderColor="LightGray"
                     TextColor="DarkBlue"
                     FontSize="Medium"
                     Keyboard="Email"
                     Grid.Row="2"
                     Grid.Column="1"
                     Grid.ColumnSpan="2"
                     Margin="0, 0, 30, 0"/>
                    <Label
                     x:Name="AvatarLabel"
                     Text="Avatar: "
                     TextColor="Black"
                     FontSize="Medium"
                     FontAttributes="Bold"
                     Grid.Row="3"
                     Margin="40, 0, 0, 0"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"/>
                    <Entry
                     x:Name="AvatarEntry"
                     Text="{Binding opm1.OperatorAvatar}"
                     Placeholder="Enter Avatar URL..."
                     PlaceholderColor="LightGray"
                     TextColor="DarkBlue"
                     FontSize="Medium"
                     Keyboard="Plain"
                     Grid.Row="3"
                     Grid.Column="1"
                     Grid.ColumnSpan="2"
                     Margin="0, 0, 30, 0"/>
                    <Button
                     x:Name="OKButton"
                     Text="OK"
                     TextColor="Black"
                     FontAttributes="Bold"
                     HorizontalOptions="Start"
                     VerticalOptions="Center"
                     WidthRequest="100"
                     HeightRequest="40"
                     Margin="0, 20, 0, 0"
                     Grid.Row="4"
                     Grid.Column="1"
                     Clicked="OKButton_Clicked"/>
                    <Button
                     x:Name="CancelButton"
                     Text="Cancel"
                     TextColor="Black"
                     FontAttributes="Bold"
                     HorizontalOptions="End"
                     VerticalOptions="Center"
                     WidthRequest="100"
                     HeightRequest="40"
                     Margin="0, 20, 40, 0"
                     Grid.Row="4"
                     Grid.Column="2"
                     Clicked="CancelButton_Clicked"/>
                </Grid>
            </ScrollView>
        </Grid>
    </ContentPage.Content>
</ContentPage>


Here is code about OperatorInfoPage.xaml.cs

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

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace App94
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class OperatorInfoPage : ContentPage
    {
        // OperatorViewModel ovm;
        // OperatorModel opm;

        // public OperatorModel opm1 { get; set; }

        OperatorModel _opm1 ;
        public OperatorModel opm1
        {
            get
            {
                return _opm1;
            }

            set
            {
                if (_opm1 != value)
                {
                    _opm1 = value;
                    OnPropertyChanged("opm1");

                }
            }

        }
        int SelectItemIndex;

        public EventHandler<OperatorModel> ReturnValue;

        public OperatorInfoPage(OperatorModel opm)
        {
            // add a bit of padding to cater to the "notch" on the iPhone.
            if (Device.RuntimePlatform == Device.iOS)
            {
                Padding = new Thickness(0, 40, 0, 0);
            }

            InitializeComponent();
            SelectItemIndex= OperatorViewModel.OperatorList.IndexOf(opm);
            
            //  ovm = _ovm;
            // opm = ovm.SelectedOperator;
            this.opm1 = opm;
            BindingContext = this;
        }

        private async void BackButton_Clicked(object sender, EventArgs e)
        {
            await Navigation.PopModalAsync();
        }

        private async void OKButton_Clicked(object sender, EventArgs e)
        {
            OperatorViewModel.OperatorList[SelectItemIndex].OperatorName = opm1.OperatorName;
            OperatorViewModel.OperatorList[SelectItemIndex].OperatorPhone = opm1.OperatorPhone;
            OperatorViewModel.OperatorList[SelectItemIndex].OperatorEmail = opm1.OperatorEmail;
            OperatorViewModel.OperatorList[SelectItemIndex].OperatorAvatar = opm1.OperatorAvatar;
            // OperatorViewModel.OperatorList.Add(opm1);

            OperatorModel operatorModel = opm1;
           
            EventHandler<OperatorModel> handler = ReturnValue;
            if (handler != null)
            {
                handler(this, operatorModel);
            }


            await Navigation.PopModalAsync();
        }

        private async void CancelButton_Clicked(object sender, EventArgs e)
        {
            await Navigation.PopModalAsync();
        }
    }
}
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Stunning stuff, @LeonLu-MSFT .
Not exactly sure how you did some of it so I might come back to ask questions, but for the time being, it all works.

0 Votes 0 ·
LeonLu-MSFT avatar image
0 Votes"
LeonLu-MSFT answered LeonLu-MSFT edited

Hello,​

Welcome to our Microsoft Q&A platform!

If do not change lots of code to achieve Delete or Add function, a straightforward way is adding static value to the OperatorList, I change the type of OperatorList from list to ObservableCollection for updating dramatically. Here is edited OperatorViewModel.

public class OperatorViewModel : INotifyPropertyChanged
    {
        private string _HFNName;

        public string HFNName
        {
            get
            {
                return _HFNName;
            }

            set
            {
                _HFNName = value;
                RaisePropertyChanged("HFNName");
            }
        }

        public OperatorViewModel()
        {
            GetOperators();
        }

        public static ObservableCollection<OperatorModel> OperatorList;
        public OperatorModel SelectedOperator;

        public async Task<bool> GetOperators()
        {
            if (OperatorList == null)
            {
                OperatorList = new ObservableCollection<OperatorModel>();
                OperatorList.Add(new OperatorModel(1, "Grime", "+61419659866", "apps@grime.net", "gs300.png"));
                OperatorList.Add(new OperatorModel(2, "Brookey", "+61419659866", "brookey@grime.net", "gmb.jpg"));
                OperatorList.Add(new OperatorModel(3, "CC", "+61422192456", "shaunachick@gmail.com", "cc.jpg"));
                OperatorList.Add(new OperatorModel(4, "Monte", "+61412595878", "monte@aussieweb.com.au", "monte2a.jpg"));
                OperatorList.Add(new OperatorModel(5, "Jeff", "+61409998197", "jeff@content2convert.com.au", "jeff.jpg"));
            }

            return true;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string prop)
        {
            if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
        }

        public bool UpdateOperator(OperatorModel opm)
        {
            SelectedOperator.OperatorName = opm.OperatorName;
            SelectedOperator.OperatorPhone = opm.OperatorPhone;
            SelectedOperator.OperatorEmail = opm.OperatorEmail;
            SelectedOperator.OperatorAvatar = opm.OperatorAvatar;

            return true;
        }
    }


Then I achieve Remove function.

private async void DeleteOperatorButton_Clicked(object sender, EventArgs e)
        {
            if (SelectModel != null)
            {

                OperatorViewModel.OperatorList.Remove(SelectModel);
                SelectModel = null;
                SelectedOperatorEntry.Text = "";
            }
            else
            {
              await  DisplayAlert("info","please select item","OK");
            }
        }


Here is all of code about the OperatorsPage.xaml.cs

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

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace App94
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class OperatorsPage : ContentPage
    {
        OperatorViewModel ovm;
        OperatorModel opm;

        // public OperatorsPage(OperatorViewModel _ovm)
        // The line above changed to the line below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
        public OperatorsPage()
        {
            // add a bit of padding to cater to the "notch" on the iPhone.
            if (Device.RuntimePlatform == Device.iOS)
            {
                Padding = new Thickness(0, 40, 0, 0);
            }

            InitializeComponent();

            // ovm = _ovm;
            // opm = ovm.SelectedOperator;
            // The 2 lines above changed to the line below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
            opm = new OperatorModel();

            BindingContext = opm;

        }

        private async void BackButton_Clicked(object sender, EventArgs e)
        {
            await Navigation.PopModalAsync();
            // The line above originally commented out at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
        }

        private async void AddOperatorButton_Clicked(object sender, EventArgs e)
        {
            await Navigation.PushModalAsync(new NewOperatorPage());
            // The line above originally commented out at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021

        }

        private async void SelectOperatorButton_Clicked(object sender, EventArgs e)
        {
            // The lines below added at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
            SelectOperatorPage page = new SelectOperatorPage();
            page.ReturnValue += delegate (object s, OperatorModel operatorModel)
            {
                BackCall(s, operatorModel);
            };

            await Navigation.PushModalAsync(page);
        }
        // The lines below added at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021

        OperatorModel SelectModel;
        private void BackCall(object s, OperatorModel model)
        {
            SelectModel = model;
            opm.OperatorName = model.OperatorName;
        }

       

        private async void DeleteOperatorButton_Clicked(object sender, EventArgs e)
        {
            if (SelectModel != null)
            {

                OperatorViewModel.OperatorList.Remove(SelectModel);
                SelectModel = null;
                SelectedOperatorEntry.Text = "";
            }
            else
            {
              await  DisplayAlert("info","please select item","OK");
            }
        }

        private async void UpdateOperatorButton_Clicked(object sender, EventArgs e)
        {
            //var operatorInfoPage = new OperatorInfoPage();
            //operatorInfoPage.BindingContext = ovm;
            //await Navigation.PushModalAsync(operatorInfoPage);
            if (opm != null)
            {

                //  var operatorInfoPage = new OperatorInfoPage(opm);
                //operatorInfoPage.BindingContext = ovm;
                //  await Navigation.PushModalAsync(operatorInfoPage);

            }


        }
    }
}


I achieve add function as well, here is NewOperatorPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App94.NewOperatorPage">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="NewOperatorPage"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />

            <Entry x:Name="OperatorName" Placeholder="OperatorName" ></Entry>
            <Entry x:Name="OperatorPhone" Placeholder="OperatorPhone" ></Entry>
            <Entry x:Name="OperatorEmail" Placeholder="OperatorEmail" ></Entry>
            <Entry x:Name="OperatorAvatar" Placeholder="OperatorAvatar" ></Entry>

            <Button Text="Update" Clicked="Button_Clicked"></Button>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>


Here is NewOperatorPage.xaml.cs

public partial class NewOperatorPage : ContentPage
    {
        public NewOperatorPage()
        {
            InitializeComponent();
        }

        private void Button_Clicked(object sender, EventArgs e)
        {
            var name=OperatorName.Text;
            var Phone= OperatorPhone.Text;
            var Email= OperatorEmail.Text;
            var Avatar =  OperatorAvatar.Text;
            OperatorViewModel.OperatorList.Add(new OperatorModel(OperatorViewModel.OperatorList.Count,name,Phone,Email,Avatar));
            Navigation.PopModalAsync();
        }
    }


Best Regards,

Leon Lu



If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@Grime May I know if you have got any chance to check my answer?

0 Votes 0 ·

@LeonLu-MSFT Thanks for your prompt response and sorry about the delayed response from me, but I hit a snag and had to repeat your solution to make sure I had not left anything out.

On compilation, an error appears in the SelectOperatorPage.xaml.cs:

94918-clipboard01.jpg

I can send the XAML and code-behind if you need it.


0 Votes 0 ·
clipboard01.jpg (43.3 KiB)

Just change it directly as following code.

protected override async void OnAppearing()
        {
            base.OnAppearing();
            await ovm.GetOperators();
            OperatorListView.ItemsSource = OperatorViewModel.OperatorList;
        }


0 Votes 0 ·
Grime avatar image
0 Votes"
Grime answered LeonLu-MSFT edited

@LeonLu-MSFT - It is close. I need to show you more than "reply" allows, so I'll show it here. Your solution compiles but only Add Operator works. Modifiy is not selectable and Delete asks to select an Operator with no means of doing that. I shall show you here the SecectOperator.xaml that I am using:


 <?xml version="1.0" encoding="utf-8" ?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="HandsFreeNotes.View.SelectOperatorPage">
    
     <ContentPage.Content>
         <Grid BackgroundColor="White">
             <Grid.RowDefinitions>
                 <RowDefinition Height="40"/>
                 <RowDefinition Height="40"/>
                 <RowDefinition Height="80"/>
                 <RowDefinition Height="*"/>
                 <RowDefinition Height="50"/>
             </Grid.RowDefinitions>
    
             <Grid.ColumnDefinitions>
                 <ColumnDefinition Width="50"/>
                 <ColumnDefinition Width="*"/>
                 <ColumnDefinition Width="50"/>
             </Grid.ColumnDefinitions>
    
             <Button
                 x:Name="BackButton"
                 Text="Back"
                 Grid.Row="0"
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 TextColor="Black"
                 FontAttributes="Bold"
                 HeightRequest="40"
                 VerticalOptions="CenterAndExpand"
                 HorizontalOptions="End"
                 Margin="0,0,20,0"
                 Clicked="BackButton_Clicked"/>
    
             <Image 
                 Source="hfn256"
                 Margin="2"
                 Grid.Row="1" 
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 HorizontalOptions="Center"
                 BackgroundColor="Transparent"/>
    
             <Label 
                 Text="Select Operator..."
                 FontSize="Large"
                 TextColor="Black"
                 FontAttributes="Bold"
                 Grid.Row="2" 
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 HorizontalOptions="Center"
                 VerticalOptions="Start"
                 Margin="20"
                 BackgroundColor="Transparent"/>
    
             <ListView
                 x:Name="OperatorListView"
                 Grid.Row="3"
                 Grid.Column="0"
                 Grid.ColumnSpan="3"
                 RowHeight="140"
                 ItemSelected="OperatorListView_ItemSelected">
                 <ListView.ItemTemplate>
                     <DataTemplate>
                         <ViewCell>
                             <ContentView>
                                 <Grid>
                                     <Grid.RowDefinitions>
                                         <RowDefinition Height="*"/>
                                     </Grid.RowDefinitions>
                                     <Grid.ColumnDefinitions>
                                         <ColumnDefinition Width="100"/>
                                         <ColumnDefinition Width="100"/>
                                         <ColumnDefinition Width="200"/>
                                     </Grid.ColumnDefinitions>
    
                                     <Image
                                         Source="{Binding OperatorAvatar}"
                                         Grid.Row="0"
                                         Grid.Column="0"
                                         HeightRequest="200"
                                         WidthRequest="100"/>
    
                                     <Label
                                         Text="{Binding OperatorName}"
                                         FontAttributes="Bold"
                                         HorizontalOptions="Start"
                                         VerticalOptions="Center"
                                         Grid.Row ="0"
                                         Grid.Column="1"/>
    
                                     <Label
                                         Text="{Binding OperatorEmail}"
                                         FontAttributes="Italic"
                                         FontSize="Micro"
                                         Grid.Row="0"
                                         Grid.Column="2"
                                         HeightRequest="30"
                                         HorizontalOptions="Start"
                                         VerticalOptions="Center"/>
    
                                     <Label
                                         Text="{Binding OperatorPhone}"
                                         FontAttributes="Italic"
                                         FontSize="Small"
                                         Grid.Row="0"
                                         Grid.Column="2"
                                         HeightRequest="30"
                                         HorizontalOptions="Start"
                                         VerticalOptions="End"/>
    
                                 </Grid>
                             </ContentView>
                         </ViewCell>
                     </DataTemplate>
                 </ListView.ItemTemplate>
             </ListView>
    
         </Grid>
     </ContentPage.Content>
 </ContentPage>

...and the code-behind, SelectOperator.xaml.cs:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
    
 using Xamarin.Forms;
 using Xamarin.Forms.Xaml;
 using HandsFreeNotes.ViewModel;
 using HandsFreeNotes.Model;
    
 namespace HandsFreeNotes.View
 {
     [XamlCompilation(XamlCompilationOptions.Compile)]
     public partial class SelectOperatorPage : ContentPage
     {
         OperatorViewModel ovm;
    
         // Added the line below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
         public EventHandler<OperatorModel> ReturnValue;
    
         public SelectOperatorPage()
         {
             // add a bit of padding to cater to the "notch" on the iPhone.
             if (Device.RuntimePlatform == Device.iOS)
             {
                 Padding = new Thickness(0, 40, 0, 0);
             }
    
             InitializeComponent();
    
             ovm = new OperatorViewModel();
    
             BindingContext = ovm;
         }
    
         protected override async void OnAppearing()
         {
             base.OnAppearing();
             await ovm.GetOperators();
             OperatorListView.ItemsSource = OperatorViewModel.OperatorList;
         }
    
         private async void BackButton_Clicked(object sender, EventArgs e)
         {
             await Navigation.PopModalAsync();
         }
    
         private async void OperatorListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
         {
             if (e.SelectedItem != null)
             {
                 // Typecast the e.SelectedItem object to an OperatorModel
    
                 // ovm.SelectedOperator = (OperatorModel)e.SelectedItem;
                 // await DisplayAlert("Alert", "Selected Operator: " + ovm.SelectedOperator.OperatorName, "Exit");
    
                 // The 2 lines above were changed to the 7 below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
    
                 OperatorModel operatorModel = (OperatorModel)e.SelectedItem;
                 ovm.SelectedOperator = operatorModel;
                 EventHandler<OperatorModel> handler = ReturnValue;
                 if (handler != null)
                 {
                     handler(this, operatorModel);
                 }
    
    
                 await Navigation.PopModalAsync();
             }
         }
     }
 }

Thanks for your persistence.


· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Your solution compiles but only Add Operator works. Modifiy is not selectable and Delete asks to select an Operator with no means of doing that. I shall show you here the >SecectOperator.xaml that I am using:

Let focus one by one requests, Lets focus on delete function, my delete function that must select an item in the listview, then user could delete



0 Votes 0 ·

Yes, I need a Delete Operator function.
That's interesting. I have compiled your App94 and it works exactly as your screenshot does.
However, when I include your code into my app, Add Operator works fine, and I can select the added Operator, but when I click the Delete Operator button, it pops up the DisplayAlert and doesn't delete the operator.
This screenshot shows that the added Operator is selected and shows the DisplayAlert.
95491-img-8478.jpg

I believe this screenshot shows that my button operation does exactly what you proposed.
95445-clipboard01.jpg


0 Votes 0 ·
img-8478.jpg (139.4 KiB)
clipboard01.jpg (220.4 KiB)
LeonLu-MSFT avatar image
0 Votes"
LeonLu-MSFT answered LeonLu-MSFT commented

Please copy my OperatorsPage.xaml.cs code in your demo. I make some changes in the BackCall method.

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

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace App94
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class OperatorsPage : ContentPage
    {
        OperatorViewModel ovm;
        OperatorModel opm;

        // public OperatorsPage(OperatorViewModel _ovm)
        // The line above changed to the line below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
        public OperatorsPage()
        {
            // add a bit of padding to cater to the "notch" on the iPhone.
            if (Device.RuntimePlatform == Device.iOS)
            {
                Padding = new Thickness(0, 40, 0, 0);
            }

            InitializeComponent();

            // ovm = _ovm;
            // opm = ovm.SelectedOperator;
            // The 2 lines above changed to the line below at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
            opm = new OperatorModel();

            BindingContext = opm;

        }

        private async void BackButton_Clicked(object sender, EventArgs e)
        {
            await Navigation.PopModalAsync();
            // The line above originally commented out at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
        }

        private async void AddOperatorButton_Clicked(object sender, EventArgs e)
        {
            await Navigation.PushModalAsync(new NewOperatorPage());
            // The line above originally commented out at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021

        }

        private async void SelectOperatorButton_Clicked(object sender, EventArgs e)
        {
            // The lines below added at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021
            SelectOperatorPage page = new SelectOperatorPage();
            page.ReturnValue += delegate (object s, OperatorModel operatorModel)
            {
                BackCall(s, operatorModel);
            };

            await Navigation.PushModalAsync(page);
        }
        // The lines below added at the behest of JessieZhang-2116 (Microsoft Q&A) 01/05/2021

        OperatorModel SelectModel;
        private void BackCall(object s, OperatorModel model)
        {
            SelectModel = model;
            opm.OperatorName = model.OperatorName;
        }

       

        private async void DeleteOperatorButton_Clicked(object sender, EventArgs e)
        {
            if (SelectModel != null)
            {

                OperatorViewModel.OperatorList.Remove(SelectModel);
                SelectModel = null;
                SelectedOperatorEntry.Text = "";
            }
            else
            {
              await  DisplayAlert("info","please select item","OK");
            }
        }

        private async void UpdateOperatorButton_Clicked(object sender, EventArgs e)
        {
            //var operatorInfoPage = new OperatorInfoPage();
            //operatorInfoPage.BindingContext = ovm;
            //await Navigation.PushModalAsync(operatorInfoPage);
            if (opm != null)
            {

                //  var operatorInfoPage = new OperatorInfoPage(opm);
                //operatorInfoPage.BindingContext = ovm;
                //  await Navigation.PushModalAsync(operatorInfoPage);

            }


        }
    }
}
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@LeonLu-MSFT Well done! Add and Delete are now working. That leaves Edit/Update Operator.

Currently, the updateOperatorButton_Clicked does nothing...

         private void UpdateOperatorButton_Clicked(object sender, EventArgs e)
         {
             // The 3 lines below added at the behest of LeonLu-MSFT (Microsoft Q&A) 06/05/2021
             if (opm != null)
             {
             }
         }

In my OperatorViewModel.cs, I have an update method ready to go:

         public bool UpdateOperator(OperatorModel opm)
         {
             SelectedOperator.OperatorName = opm.OperatorName;
             SelectedOperator.OperatorPhone = opm.OperatorPhone;
             SelectedOperator.OperatorEmail = opm.OperatorEmail;
             SelectedOperator.OperatorAvatar = opm.OperatorAvatar;
    
             return true;
         }

...and my OperatorInfoPage.xaml and code-behind can be found in my original post.

Nearly done.

0 Votes 0 ·

@LeonLu-MSFT As you might have guessed, I want to bring the Operators into a database.
Ideally, I'd like the CRUD operations (Create or add, Read, Update and Delete) that you helped develop to be methods in my OperatorViewModel.cs.
THEN, I want the Operators to be held in an SQLite database with CRUD functionality. Can you help me do that?

0 Votes 0 ·

You can open a new thread about this CRUD function and write specific needs (which kind of DB, table design) clearly in the new thread. You can achieve the add and delete function firstly.

1 Vote 1 ·