0
votes

I have a simple app that has a PicListPage (picture list). The xaml and code behind allow picking a picture from the Android emulator gallery or from taking a picture.

The selected picture (or new picture) does not show up in an Image control. I have not been able to find a solution through a web search. This code was copied from a tutorial. Putting a breakpoint at the NewImage.Source line shows that there is a non-null value for the currentimage.

Any help would be appreciated. The MS Xamarin Forums won't allow me to register or log in so I can't ask the question there.

Jim Durbin [email protected]

Here is the 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"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="MyStuff.PicListPage">
    <ContentPage.ToolbarItems>
        <ToolbarItem x:Name="selectImageButton"
            Text="Select Image"
            Command="{Binding SelectImageCommand}"/>
        <ToolbarItem x:Name="takePicButton"
            Text="Take Picture"
            Command="{Binding TakePictureCommand}"
            CommandParameter="{Binding NewImage}"/>
        <ToolbarItem x:Name="deleteButton"
            Text="Delete"
            Command="{Binding DeletePictureCommand}"
            CommandParameter="{Binding SelectedImage}"/>
    </ContentPage.ToolbarItems>
    <ContentPage.Content>
            <StackLayout>
                <Label Text="Picture List page"
           HorizontalOptions="Center"
           FontSize="Large"
           FontAttributes="Bold"/>
            <Frame BorderColor="Black"
                   WidthRequest="350"
                   HeightRequest="350"
                   Margin="10,0,10,0">
                <FlexLayout Direction="Row">
                    **<Image x:Name="NewImage"**
                           IsVisible="true"
                           Aspect="AspectFit"
                           Source="{Binding NewImmage, Mode=TwoWay}"
                           Margin="10,0,10,0"
                           WidthRequest="350"
                           HeightRequest="350"
                           HorizontalOptions="CenterAndExpand"
                           VerticalOptions="CenterAndExpand">
                    </Image>
                </FlexLayout>
            </Frame>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Here is the code behind - first the command code for selecting a picture

    using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;

namespace MyStuff.ViewModel.Commands
{
    public class SelectImageCommand : ICommand
    {
        private PicListPageVM viewmodel;

        public event EventHandler CanExecuteChanged;

        public SelectImageCommand(PicListPageVM viewmodel)
        {
            this.viewmodel = viewmodel;
        }
        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            viewmodel.SelectImage();
        }
    }
}

And here is the ViewModel code snippet that copies the image from the emulated Gallery which has 5 pictures in it.

    using MyStuff.Model;
using MyStuff.ViewModel.Commands;
using Plugin.Media;
using Plugin.Media.Abstractions;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Xamarin.Forms;

namespace MyStuff.ViewModel
{
    public class PicListPageVM : INotifyPropertyChanged
    {
        public ObservableCollection<PicList> PicLists { get; set; }
        public TakePictureCommand TakePictureCommand { get; set; }
        public SelectImageCommand SelectImageCommand { get; set; }
        public DeletePictureCommand DeletePictureCommand { get; set; }

        private Image newimage;
        public Image NewImage
        {
            get { return newimage; }
            set
            {
                newimage = value;
                OnPropertyChanged("NewImage");
            }
        }

        public PicListPageVM()
        {
            SelectImageCommand = new SelectImageCommand(this);
            TakePictureCommand = new TakePictureCommand(this);
            DeletePictureCommand = new DeletePictureCommand(this);
            NewImage = new Image();
            NewImage.IsOpaque = false;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

            public async void SelectImage()
        {
            await CrossMedia.Current.Initialize();
            if (!CrossMedia.Current.IsPickPhotoSupported)
            {
                await App.Current.MainPage.DisplayAlert("Information", "Can't select pictures on this device", "OK");
                return;
            }
            var mediaoptions = new PickMediaOptions()
            {
                PhotoSize = PhotoSize.Small
            };
            var selectedImageFile = await CrossMedia.Current.PickPhotoAsync(mediaoptions);
            if (selectedImageFile == null)
            {
                await App.Current.MainPage.DisplayAlert("Information", "No image selected.", "OK");
                return;
            }
            **var currentimage = ImageSource.FromStream(() => selectedImageFile.GetStream());
            NewImage.Source = currentimage;**
        }
2

2 Answers

0
votes

first, you misspelt the name of your property ("NewImage") in the binding (TwoWay binding also doesn't make sense here)

<Image x:Name="NewImage" Source="{Binding NewImmage, Mode=TwoWay}" .. />

second, in your VM NewImage is of type Image, which is not right. Image is a UI control, not a data type. Use string instead

    private string newimage;
    public string NewImage
    {
        get { return newimage; }
        set
        {
            newimage = value;
            OnPropertyChanged("NewImage");
        }
    }

finally, when you select your image set the VM property to the image path

NewImage = selectedImageFile.AlbumPath;
  
0
votes

This issue is resolved. Thanks to @Jason and a little further hacking. The key issues were 1) a typo in the binding 2) The binding needed to point to a property that had datatype string instead of an Image UI element - which in turn pointed to a file path and 3) setting the bound string to point to the selectedImageFile.Path rather than to selectedImageFile.AlbumPath.