Преобразованное значение не отображается в пользовательском интерфейсе GridView - PullRequest
0 голосов
/ 02 мая 2020

У меня есть функция, которая берет объект из файла хранилища и создает его эскиз. Эта функция находится в значении конвертера, так как у нас есть более 10.000 файлов, которые будут показаны в медиа галерее. Миниатюра будет сгенерирована в файле, когда миниатюра еще не создана для файла хранения.

Проблема в том, что пользовательский интерфейс GridView не обновляется после создания эскиза / обновления объекта. Миниатюра будет отображаться только в том случае, если я прокручиваю достаточно далеко и снова прокручиваю вверх.

public class MediaFile : INotifyPropertyChanged
{
    // Declare the event
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    private ImageSource _thumbnail = null;

    public ImageSource Thumbnail
    {
        get { return _thumbnail; }
        set
        {
            _thumbnail = value;
            // Call OnPropertyChanged whenever the property is updated
            OnPropertyChanged("Thumbnail");
        }
    }

    protected void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChanged(this, e);
    }

    // Create the OnPropertyChanged method to raise the event
    // The calling member's name will be used as the parameter.
    protected void OnPropertyChanged(string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

Это класс так называемого MediaFile. Как вы можете видеть, я уже реализовал событие измененного свойства.

   <DataTemplate x:Key="GridMedia_DataTemplate" x:DataType="MediaFile">
    <Grid Style="{StaticResource Faves_Grid}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>

        <Image Grid.Row="1" Grid.RowSpan="2" Margin="0 14 0 -12" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" Stretch="UniformToFill" VerticalAlignment="Stretch" Source="{x:Bind Converter={StaticResource ThumbnailGenerator}, Mode=OneWay}"/>
    </Grid>
</DataTemplate>

Вот шаблон данных для вида сетки. Как видите, для ImageSource мы используем конвертер, чтобы получить / сгенерировать миниатюру.

public object Convert(object value, Type targetType, object parameter, string language)
    {
        try
        {
            if(value is MediaFile)
            {
                MediaFile file = value as MediaFile;
                //generate Thumbnail
                int width = 160;
                int height = 90;

                var pathFileTemp = $@"{FileLocations.MediaPath}";
                try
                {
                    StorageFile originalFile = StorageFile.GetFileFromPathAsync(pathFileTemp + file.Id).AsTask().Result;
                    if (originalFile != null)
                    {
                        //check extention
                        if (file.Extension.ToLower().Contains("pdf"))
                        {
                            GetThumbnailForPDF(file).GetAwaiter();
                            return file.Thumbnail;
                        }
                        else if (file.Extension.ToLower().Contains("jpg") ||
                            file.Extension.ToLower().Contains("gif") ||
                            file.Extension.ToLower().Contains("png") ||
                            file.Extension.ToLower().Contains("jpeg"))
                        {
                            GetThumbnailForImage(file).GetAwaiter();
                            return file.Thumbnail;
                        }
                    }
                    return new BitmapImage(new Uri("ms-appx:///Assets/Icon/placeholder_img.jpg", UriKind.Absolute));
                }
                catch (Exception)
                {
                   return new BitmapImage(new Uri("ms-appx:///Assets/Icon/placeholder_img.jpg", UriKind.Absolute));
                }
            }
            return null;
        }
        catch (Exception)
        {
            return null;
        }
    }

На данный момент мы создаем только миниатюру для PDF и изображений. Помимо этого мы вернем заполнитель миниатюру.

        <controls1:AdaptiveGridView Grid.Row="1" DesiredWidth="288" x:Name="ListView_MediaLibrary" Grid.ColumnSpan="4" ItemTemplate="{StaticResource GridMedia_Adaptive__DataTemplate}" Margin="0 0 -8 -20" SelectionChanged="ListView_MediaLibrary_SelectionChanged" ItemsSource="{Binding Source={StaticResource mediaFilesSource}, Mode=OneWay}">
        </controls1:AdaptiveGridView>

И вот как мы связываем список с GridView.

1 Ответ

0 голосов
/ 04 мая 2020

Пожалуйста, попробуйте использовать Converter для обработки простого преобразования вместо асинхронного преобразования с использованием ввода-вывода.

Вы можете попробовать преобразовать DataTemplate в UserControl и преобразовать файл операции logi c Converter в обратный вызов изменения свойства зависимостей внутри элемента управления.

Попробуйте следующие шаги:

  1. Создайте метод сравнения для класса MediaFile (Предположим, что есть уникальная Id собственность)
public class MediaFile : INotifyPropertyChanged
{
   //... other code
   public override bool Equals(object obj)
   {
       return obj is MediaFile mediaFile &&
              Id == mediaFile.Id;
   }
}
Создать UserControl

MyMediaFileItem.xaml

<UserControl
    ...>

    <Grid>
        <!-- your other code -->
        <Image x:Name="ThumbnailImage"/>
    </Grid>
</UserControl>

MyMediaFileItem.xaml.cs

public MediaFile Data
{
    get { return (MediaFile)GetValue(DataProperty); }
    set { SetValue(DataProperty, value); }
}

// Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
    DependencyProperty.Register("Data", typeof(MediaFile), typeof(MyMediaFileItem), new PropertyMetadata(null,new PropertyChangedCallback(Data_Changed)));

private static void Data_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if(e.NewValue!=null && !e.NewValue.Equals(e.OldValue) && e.NewValue is MediaFile data)
    {
        var instance = d as MyMediaFileItem;
        // get a bitmapImage through the convert method
        instance.ThumbnailImage.Source = bitmapImage;
    }
}
Использование
<DataTemplate x:Key="GridMedia_DataTemplate" x:DataType="MediaFile">
    <controls:MyMediaFileItem Data="{Binding}"/>
</DataTemplate>

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...