ImageGalleryControl不会触发

时间:2018-04-04 11:41:30

标签: c# xaml xamarin xamarin.forms

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

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

我在调试时发现了比较这两种方法的问题,而在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 });
    }
}

然后我下载图像并将它们放入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>

这就是Control,它是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;
    }
}

1 个答案:

答案 0 :(得分:1)

  1. 尝试引发Images属性的Propertychanged事件,例如:PropertyChanged(nameof(Images))。
  2. 然后要验证您是否在同一ViewModel实例上,可以在页面中订阅BindingContextChanged事件,并验证您的VM对象是否在更改。
  3. 我建议使用ObservableCollection作为: public ObservableCollection<> Images {get;set;} = new ObservableCollection<>();

具有通用ImageModel。 您不需要私有字段,这没有任何意义。