I'm attempting to download an image in bytes from a server, but the image won't display. I get a proper byte array and resize it. It works adding picture from the camera but doesn't work when adding them from the internet.
I've confirmed that the image is saved correctly, and downloaded properly as I can copy the byte Array and display it using the byte array string.
I found the problem comparing the two methods while debugging, and in the execturepickcommand
it triggers my "ItemSourceChanged"
method but it doesn't trigger with the AddImages
method.
The Collection
public class ImageGalleryPageModel { public ObservableCollection<ImageModel> Images { get { return images; } } private ObservableCollection<ImageModel> images = new ObservableCollection<ImageModel>(); }
This works adding the Pictures from this class
private async Task ExecutePickCommand() { MediaFile file = await CrossMedia.Current.PickPhotoAsync(); if (file == null) return; byte[] imageAsBytes; using (MemoryStream memoryStream = new MemoryStream()) { file.GetStream().CopyTo(memoryStream); file.Dispose(); imageAsBytes = memoryStream.ToArray(); } if (imageAsBytes.Length > 0) { IImageResizer resizer = DependencyService.Get<IImageResizer>(); imageAsBytes = resizer.ResizeImage(imageAsBytes, 1080, 1080); ImageSource imageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes)); Images.Add(new ImageModel { Source = imageSource, OrgImage = imageAsBytes }); } }
Then I download the images and put them into the Collection,
private void AddTheImages(int imageIssueId) { var imageData = App.Client.GetImage(imageIssueId); byte[] imageAsBytes = imageData.Item1; if (imageAsBytes.Length > 0) { IImageResizer resizer = DependencyService.Get<IImageResizer>(); imageAsBytes = resizer.ResizeImage(imageAsBytes, 1080, 1080); ImageSource imageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes)); ImageGalleryViewModel.Images.Add(new ImageModel { Source = imageSource, OrgImage = imageAsBytes }); } }
Xaml
<freshMvvm:FreshBaseContentPage NavigationPage.HasNavigationBar="False" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:freshMvvm="clr-namespace:FreshMvvm;assembly=FreshMvvm" xmlns:converters="clr-namespace:ASFT.Converters;assembly=ASFT" xmlns:controls="clr-namespace:ASFT.Controls;assembly=ASFT" x:Class="ASFT.Pages.IssuePage" Padding="4,25,4,4" x:Name="IssuePages"> ... <!--PictureGallery--> <Label Text="IMAGES" HorizontalTextAlignment="Start" VerticalTextAlignment="Center" Style="{StaticResource Labelfont}" TextColor="White" /> <Grid BindingContext="{Binding ImageGalleryViewModel}"> <Grid.RowDefinitions> <RowDefinition Height="128" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <controls:ImageGalleryControl Grid.Row="0" ItemsSource="{Binding Images}"> <controls:ImageGalleryControl.ItemTemplate> <DataTemplate> <Image Source="{Binding Source}" Aspect="AspectFit"> <Image.GestureRecognizers> <TapGestureRecognizer Command="{Binding Path=BindingContext.PreviewImageCommand, Source={x:Reference IssuePages}}" CommandParameter="{Binding ImageId}" /> </Image.GestureRecognizers> </Image> </DataTemplate> </controls:ImageGalleryControl.ItemTemplate> </controls:ImageGalleryControl> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Button Grid.Column="0" Text="Add photo" Command="{Binding CameraCommand}" /> <Button Grid.Column="1" Text="Pick photo" Command="{Binding PickCommand}" /> </Grid> </Grid> <Label Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="3" Text="{Binding ImageText}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="White" /> ... </freshMvvm:FreshBaseContentPage>
And this is the Control, it is the itemsourcechanged which is what is not triggering.
private readonly StackLayout imageStack; public ImageGalleryControl() { this.Orientation = ScrollOrientation.Horizontal; imageStack = new StackLayout { Orientation = StackOrientation.Horizontal }; this.Content = imageStack; } public new IList<View> Children { get { return imageStack.Children; } } public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create<ImageGalleryControl, IList> ( view => view.ItemsSource, default(IList), BindingMode.TwoWay, propertyChanging: (bindableObject, oldValue, newValue) => { ((ImageGalleryControl)bindableObject).ItemsSourceChanging(); }, propertyChanged: (bindableObject, oldValue, newValue) => { ((ImageGalleryControl)bindableObject).ItemsSourceChanged(bindableObject, oldValue, newValue); } ); public IList ItemsSource { get { return (IList)GetValue(ItemsSourceProperty); } set { SetValue(ItemsSourceProperty, value); } } private void ItemsSourceChanging() { if (ItemsSource == null) return; } private void CreateNewItem(IList newItem) { View view = (View)ItemTemplate.CreateContent(); if (view is BindableObject bindableObject) bindableObject.BindingContext = newItem; imageStack.Children.Add(view); } private void ItemsSourceChanged(BindableObject bindable, IList oldValue, IList newValue) { if (ItemsSource == null) return; if (newValue is INotifyCollectionChanged notifyCollection) { notifyCollection.CollectionChanged += (sender, args) => { if (args.NewItems != null) { if (args.NewItems.Count > 0) { foreach (object newItem in args.NewItems) { View view = (View)ItemTemplate.CreateContent(); if (view is BindableObject bindableObject) bindableObject.BindingContext = newItem; imageStack.Children.Add(view); } } } else { imageStack.Children.Clear(); foreach (object item in ItemsSource) { View view = (View)ItemTemplate.CreateContent(); BindableObject bindableObject = (BindableObject) view; if (bindableObject != null) bindableObject.BindingContext = item; imageStack.Children.Add(view); } } if (args.OldItems != null) { // not supported } }; } } public DataTemplate ItemTemplate { get; set; } public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create<ImageGalleryControl, object> ( view => view.SelectedItem, null, BindingMode.TwoWay, propertyChanged: (bindable, oldValue, newValue) => { ((ImageGalleryControl)bindable).UpdateSelectedIndex(); } ); public object SelectedItem { get { return GetValue(SelectedItemProperty); } set { SetValue(SelectedItemProperty, value); } } private void UpdateSelectedIndex() { if (SelectedItem == BindingContext) return; SelectedIndex = Children .Select(c => c.BindingContext) .ToList() .IndexOf(SelectedItem); } public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create<ImageGalleryControl, int> ( carousel => carousel.SelectedIndex, 0, BindingMode.TwoWay, propertyChanged: (bindable, oldValue, newValue) => { ((ImageGalleryControl)bindable).UpdateSelectedItem(); } ); public int SelectedIndex { get { return (int)GetValue(SelectedIndexProperty); } set { SetValue(SelectedIndexProperty, value); } } private void UpdateSelectedItem() { SelectedItem = SelectedIndex > -1 ? Children[SelectedIndex].BindingContext : null; } }
public ObservableCollection<> Images {get;set;} = new ObservableCollection<>();
with a generic ImageModel. You don't need a private field, it doesn't make a lot of sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With