Yet Another Simple Binding Question

Grime 786 Reputation points
2021-10-15T06:10:28.223+00:00

This follows on from my query yesterday that was successfully answered by @Kyle Wang .
I'm adding a new person to a database. This person is an "Operator" and each new operator has a few attributes:

  • ID (automatically incremented)
  • Name
  • Phone
  • Email
  • Avatar

I have created a constructor for the OperatorModel which caters to all these attributes.

        public OperatorModel(int operatorID, string operatorName, string operatorPhone, string operatorEmail, string operatorAvatar)  
        {  
            OperatorID = operatorID;  
            OperatorName = operatorName;  
            OperatorPhone = operatorPhone;  
            OperatorEmail = operatorEmail;  
            OperatorAvatar = operatorAvatar;  
        }  

I can cater to the first four simply, such as the Name (in xaml):

                    <Label  
                        x:Name="NameLabel"  
                        Text="Name: "  
                        TextColor="Black"  
                        FontSize="18"  
                        FontAttributes="Bold"  
                        Grid.Row="0"  
                        Grid.Column="0"  
                        Margin="40, 0, 0, 0"  
                        HorizontalOptions="End"  
                        VerticalOptions="Center"/>  
  
                    <Entry  
                        x:Name="NameEntry"  
                        Text="{ Binding OperatorName}"  
                        Placeholder="Enter a name/callsign (no spaces)"  
                        PlaceholderColor="LightGray"  
                        TextColor="Green"  
                        FontSize="18"  
                        FontAttributes="Bold,Italic"  
                        Keyboard="Text"  
                        Grid.Row="0"  
                        Grid.Column="1"  
                        Margin="0, 0, 20, 0"/>  

But when it comes to the avatar, I have to go and select an image from the gallery and then get its path, which I can do, but how do I then assign that path to the binding, OperatorAvatar?

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,297 questions
0 comments No comments
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 68,741 Reputation points Microsoft Vendor
    2021-10-15T13:24:52.447+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    I have to go and select an image from the gallery and then get its path, which I can do, but how do I then assign that path to the binding, OperatorAvatar?

    You can use Xamarin.Essentials: File Picker to select the image from the gallery, but you also need to copy the image to your application's interal storage, If you use external path, this image moved or delete, your image cannot be showed correctly and your path is wrong and need to update DB.

    So you can refer to following code to select the image from the gallery , then copy it to your application's internal storage, use and save the internal path to your DB.

       async Task<FileResult> PickAndShow(PickOptions options)  
               {  
                   try  
                   {  
                       var result = await FilePicker.PickAsync(options);  
                       if (result != null)  
                       {  
                           Text = $"File Name: {result.FileName}";  
                           if (result.FileName.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ||  
                               result.FileName.EndsWith("png", StringComparison.OrdinalIgnoreCase))  
                           {  
                               
                               //copy image to your application's path  
                               var newFile = Path.Combine(FileSystem.AppDataDirectory, result.FileName);  
                               using (var stream = await result.OpenReadAsync())  
                               using (var newStream = File.OpenWrite(newFile))  
                                   await stream.CopyToAsync(newStream);  
         
                               ImagePath = newFile;  
         
                               // Image = ImageSource.FromStream(() => stream);  
                           }  
                       }  
         
                       return result;  
                   }  
                   catch (Exception ex)  
                   {  
                       // The user canceled or something went wrong  
                   }  
         
                   return null;  
               }  
     
    

    Here is ViewModel, I make a test to pick the image, then make it to display to the Image control. After your image shown in the layout, you can save path to your DB in GetImageCommand .

       public class MyViewModel: INotifyPropertyChanged  
           {  
               //add a property to the ViewModel, if the image need to be show in your layout.  
               string imagePath;  
               public string ImagePath  
               {  
                   set  
                   {  
                       if (imagePath != value)  
                       {  
                           imagePath = value;  
                           OnPropertyChanged("ImagePath");  
         
                       }  
                   }  
                   get  
                   {  
                       return imagePath;  
                   }  
               }  
               public event PropertyChangedEventHandler PropertyChanged;  
         
               protected virtual void OnPropertyChanged(string propertyName)  
               {  
                   PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
               }  
               public MyViewModel()  
               {  
                   GetImageCommand = new Command<object>(async (key) => {  
         
                     await  PickAndShow(PickOptions.Images);  
         
                       // After your image shown in the layout, you can save path to your DB at here  
                   });  
               }  
         
         
         
               public ICommand GetImageCommand { protected set; get; }  
         
                
                
               string Text;  
               async Task<FileResult> PickAndShow(PickOptions options)  
               {  
                   try  
                   {  
                       var result = await FilePicker.PickAsync(options);  
                       if (result != null)  
                       {  
                           Text = $"File Name: {result.FileName}";  
                           if (result.FileName.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ||  
                               result.FileName.EndsWith("png", StringComparison.OrdinalIgnoreCase))  
                           {  
                               
                               //copy image to your application's path  
                               var newFile = Path.Combine(FileSystem.AppDataDirectory, result.FileName);  
                               using (var stream = await result.OpenReadAsync())  
                               using (var newStream = File.OpenWrite(newFile))  
                                   await stream.CopyToAsync(newStream);  
         
                               ImagePath = newFile;  
         
                               // Image = ImageSource.FromStream(() => stream);  
                           }  
                       }  
         
                       return result;  
                   }  
                   catch (Exception ex)  
                   {  
                       // The user canceled or something went wrong  
                   }  
         
                   return null;  
               }  
         
           }  
    

    Here is my layout.

       <StackLayout>  
               <Image Source="{Binding ImagePath}" />  
         
               <Button Text="Picker Image"      
                       Command="{ Binding GetImageCommand }"  
                       CommandParameter="{Binding .}" ></Button>  
           </StackLayout>  
    

    Here is my layout background code.

       public partial class MainPage : ContentPage  
           {  
               public MainPage()  
               {  
                   InitializeComponent();  
                   this.BindingContext = new MyViewModel();  
               }  
           }  
    

    Here is running screenshot.

    140911-image.png

    Best Regards,

    Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    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.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful