question

Grime avatar image
0 Votes"
Grime asked Grime commented

Yet Another Simple Binding Question

This follows on from my query yesterday that was successfully answered by @KyleWang-MSFT.
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?











dotnet-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.

1 Answer

LeonLu-MSFT avatar image
1 Vote"
LeonLu-MSFT answered Grime commented

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.



image.png (23.0 KiB)
· 6
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? I am glad to help if you have any other questions

0 Votes 0 ·

I think this is far too complex. I simply need to insert the path to the avatar image (which I have determined to be "PhotoPath") into the Avatar bit of my OperatorModel Binding Context. This is what it looks like going into the database...

             var todoItem = (OperatorModel)BindingContext;
             HFNDatabase database = await HFNDatabase.Instance;
             await database.SaveItemAsync(todoItem);
             await Navigation.PopModalAsync();   
0 Votes 0 ·

When you save the path to the database, then you want to binding the path to the OperatorAvatar ?

0 Votes 0 ·

I think so. I want the avatar path (which I call "PhotoPath") to be inserted into the todoItem in line 1 above before being saved to the database in lines 2 & 3.

0 Votes 0 ·
Show more comments