ImageGalleryControl 未触发

Posted

技术标签:

【中文标题】ImageGalleryControl 未触发【英文标题】:ImageGalleryControl not triggering 【发布时间】:2018-09-13 23:04:52 【问题描述】:

我正在尝试从服务器下载以字节为单位的图像,但图像不会显示。我得到一个正确的字节数组并调整它的大小。它可以从相机添加图片,但从互联网添加图片时不起作用。

我已确认图像已正确保存并正确下载,因为我可以复制字节数组并使用字节数组字符串显示它。

我在调试时发现了比较这两种方法的问题,在execturepickcommand 中它触发了我的"ItemSourceChanged" 方法,但在AddImages 方法中没有触发。

收藏

public class ImageGalleryPageModel

    public ObservableCollection<ImageModel> Images
    
        get  return images; 
    

    private ObservableCollection<ImageModel> images = new ObservableCollection<ImageModel>();

这可以从这个类中添加图片

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 );
    

然后我下载图像并将它们放入集合中,

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>

这是控件,它是未触发的 itemsourcechanged。

    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;
    

【问题讨论】:

在没有调整大小的情况下可以工作吗?尝试将下载的图像保存到磁盘并打开它 - 可能你的字节有问题 没有 reziser 就无法工作,字节没有问题,我在一个页面上测试了它们,该页面采用字节数组并将其转换为图像,完美显示图像但是当excat 相同的数组进入集合 你试过网络客户端下载图片吗? var webClient = new WebClient(); byte[] imageBytes = webClient.DownloadData("google.com/images/logos/ps_logo2.png"); 不确定这里是否有用。 是的,也试过了。不知道为什么,为什么添加图像的一种情况有效而另一种无效。它们几乎相同。唯一的区别是我从互联网上获取另一个文件,从手机摄像头获取另一个文件。 您是否 100% 确定将它们添加到同一 ImageGalleryPageModel 实例中? 【参考方案1】:
    尝试为图像属性引发 Propertychanged 事件,例如:PropertyChanged(nameof(Images))。 然后,为了验证您在同一个 ViewModel 实例上,您可以订阅页面中的 BindingContextChanged 事件并验证您的 VM 对象是否正在更改。 我建议使用 ObservableCollection 作为: public ObservableCollection<> Images get;set; = new ObservableCollection<>();

使用通用 ImageModel。 你不需要私有字段,它没有多大意义。

【讨论】:

嘿老兄,感谢您的回答。但这是一篇将近 3 年的帖子,哈哈,我已经改进了很久,可以编写更好的代码,甚至 Xamarin 也有了很大的改进。无论如何都接受了你的答案 m8

以上是关于ImageGalleryControl 未触发的主要内容,如果未能解决你的问题,请参考以下文章

触发器在操作时未触发

更新触发器未在 plpgsql 中触发

Oracle SQL - 插入前触发器未触发

onConfigurationChanged 未触发

为啥本地通知未针对 UNCalendarNotificationTrigger 触发

AVPlayerItemDidPlayToEndTimeNotification 未触发