Не удается отобразить изображение со съемного SD-пакета — UWP Windows IOT

Я сделал все необходимое для получения доступа к файлам, расположенным на SD-карте моего устройства IOT (DragonBoard 410c).

У меня есть все FileTypeAssociations

    <Capability Name="internetClient" />
    <Capability Name="privateNetworkClientServer" />
    <Capability Name="internetClientServer" />
    <uap:Capability Name="userAccountInformation" />
    <uap:Capability Name="removableStorage" />
    <uap:Capability Name="enterpriseAuthentication" />

Я МОГУ видеть и перебирать файлы на SD-карте

StorageFolder removablelDevices = Windows.Storage.KnownFolders.RemovableDevices;
StorageFolder sdCard = (await removablelDevices.GetFoldersAsync()).FirstOrDefault();
var files = await nm.GetFilesAsync();

foreach (var file in files)
{
    DebugText(file.Path);
    //E:\Photo1.jpg
    //E:\Photo2.jpg
}

Я устанавливаю ImageSource ImageBrush фона для этих изображений в слайд-шоу.

private ImageSource _CurrentPicture;
public ImageSource CurrentPicture { get { return _CurrentPicture; } set { Set(ref _CurrentPicture, value); } }

<ImageBrush  Stretch="UniformToFill" ImageSource="{x:Bind ViewModel.CurrentPicture, Mode=OneWay}"/>

Картинки не отображаются (E:\Photo1.jpg и т.д.)

Я могу перебирать общие файлы на локальном сервере в режиме разработки, поэтому мои изображения отображаются на моем фоне в этом сценарии.


Я обновляю фон с помощью DispatchTimer.
Теперь, когда доступ к файлам асинхронный, я сталкиваюсь с асинхронным адом.

public void TimerSetup()
{
    SlideShowTimer = new DispatcherTimer();
    SlideShowTimer.Tick += SlideShowTimer_Tick;
    SlideShowTimer.Interval = new TimeSpan(0, 0, SlideShowChangeIntervalSeconds);
    SlideShowTimer.Start();

}
void SlideShowTimer_Tick(object sender, object e)
{
    ChangeBackground();
}
public async Task ChangeBackground()
{
    var nextIndex = RandomGenerator.Next(0, SlideShowFiles.Length);
    var fileName = SlideShowFiles[nextIndex];
    var file = await StorageFile.GetFileFromPathAsync(fileName);
    var stream = await file.OpenAsync(FileAccessMode.Read);
    await CurPicImage.SetSourceAsync(stream);
    await Task.CompletedTask;
}

person Terrence    schedule 02.02.2019    source источник


Ответы (1)


Свойство ImageSource в ImageBrush не преобразует автоматически пути к файлам в объект ImageSource. Вам нужно будет сделать преобразование в вашем коде:

var file = await StorageFile.GetFileFromPathAsync(@"E:\Photo1.jpg");
var stream = await file.OpenAsync(FileAccessMode.Read);
var bitmapImage = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
imageBrush.ImageSource = bitmapImage;
await bitmapImage.SetSourceAsync(stream);

Выше приведен простой (быстрый и грязный) способ установить кисть изображения из пути к файлу в коде. Более элегантным способом будет реализация IValueConverter для использования в вашей привязке данных. Поскольку вы хотите, чтобы привязка данных была асинхронной и не блокировала поток пользовательского интерфейса, требуется немного больше кода. Подробности о том, как реализовать асинхронный IValueConverter, можно найти в этом превосходном ответе: Асинхронная реализация IValueConverter

person Stefan Wick MSFT    schedule 03.02.2019
comment
Стефан, большое спасибо за ваше решение. Я был бы рад, если бы вы могли показать мне пример того, как IValueConverter делает это. В долгосрочной перспективе я хочу кодировать с использованием лучших практик. - person Terrence; 03.02.2019
comment
Я отредактировал свой ответ, указав, как реализовать асинхронный IValueConverter, на который в прошлом был дан ответ по другому вопросу. - person Stefan Wick MSFT; 03.02.2019
comment
Стефан, ваше решение сработало. Спасибо. Я отредактировал свой пост, чтобы показать новый код, и теперь вы видите, что я в асинхронном аду, потому что мой DispatchTimer не асинхронный. Думаю, мне придется следовать асинхронному маршруту IValueConverter. - person Terrence; 03.02.2019
comment
С какой именно проблемой вы столкнулись с DispatcherTimer? Я не могу сказать из обновленного вопроса. Возможно, стоит опубликовать отдельный вопрос, но он должен быть довольно простым. - person Stefan Wick MSFT; 03.02.2019
comment
Чтобы вызвать ChangeBackground(), я должен превратить метод SlideShowTimer_Tick в асинхронный метод, когда я делаю это, код обработчика событий SlideShowTimer.Tick += SlideShowTimer_Tick; взрывается. - person Terrence; 03.02.2019
comment
Я также разместил другой связанный вопрос об использовании Uri вместо потока для этой проблемы Network Uri vs Local Uri - person Terrence; 03.02.2019
comment
Чтобы исправить ошибку DispatcherTimer, просто измените функцию на public async void ChangeBackground() и удалите await Task.CompletedTask; линия. - person Stefan Wick MSFT; 03.02.2019
comment
Стефан, когда я вношу эти изменения, бегущая строка тикает, и источник растрового изображения устанавливается, но изображение не отображается на экране. - person Terrence; 03.02.2019
comment
Меня устраивает. Поскольку у вас это сработало для одного файла, нет причин, по которым это не сработало бы в цикле или по таймеру. Я думаю, вам нужно немного отладить свой код. Если это не поможет, я бы предложил вам открыть новый вопрос о проблеме DispatcherTimer, с которой вы столкнулись, и включить полное воспроизведение. Например, в вашем последнем обновлении непонятно, что такое «CurPicImage». Этого нет в вашем XAML, поэтому мы можем только строить догадки. - person Stefan Wick MSFT; 04.02.2019
comment
Ты человек. Я переключался между моим исходным ImageSource и BitmapImage. Теперь они выровнены, и это работает. Большое спасибо за то, что остаетесь со мной в этом. - person Terrence; 04.02.2019
comment
Рад, что теперь это работает — получайте удовольствие от своего проекта IoT! Пожалуйста, отметьте как ответ, чтобы мы исключили это из списка. Ваше здоровье! - person Stefan Wick MSFT; 04.02.2019