C# 如何在image.source中为listView的每个元素定期设置图像?
我需要在ListView的每个查看器中设置从rest服务获取的图像。这些图像会定期更改以创建“gif”效果,一段时间后,我会调用该服务以获取有关网络摄像头的更新图像。问题是并不是所有的图像都被设置,只是其中的一部分,有时甚至没有一个图像被设置 我的代码如下:C# 如何在image.source中为listView的每个元素定期设置图像?,c#,image,xamarin.forms,task,ffimageloading,C#,Image,Xamarin.forms,Task,Ffimageloading,我需要在ListView的每个查看器中设置从rest服务获取的图像。这些图像会定期更改以创建“gif”效果,一段时间后,我会调用该服务以获取有关网络摄像头的更新图像。问题是并不是所有的图像都被设置,只是其中的一部分,有时甚至没有一个图像被设置 我的代码如下: public class WebcamListViewModel : BaseViewModel { public ICommand InitializeWebcamsCommand { set; get; } publi
public class WebcamListViewModel : BaseViewModel
{
public ICommand InitializeWebcamsCommand { set; get; }
public ICommand OpenVideoWebcamCommand { set; get; }
private List<Webcam> _ListOfWebcam { get; set; }
public List<Webcam> ListOfWebcam
{
get { return _ListOfWebcam; }
set
{
_ListOfWebcam = value;
OnPropertyChanged();
}
}
private IFolder folder;
private int _Counter { get; set; }
public int Counter
{
get { return _Counter; }
set
{
_Counter = value;
OnPropertyChanged();
}
}
private Task SetFrameOnViewTask;
private Task DownloadFramesTask;
CancellationTokenSource tokenSourceSetFrame = new CancellationTokenSource();
CancellationTokenSource tokenSourceDownloadFrames = new CancellationTokenSource();
CancellationToken cancellationTokenSetFrame;
CancellationToken cancellationTokenDownloadFrames;
public WebcamListViewModel(INavigationService navigationService, IApiAutostradeManagerFactory apiAutostradeManagerFactory) : base(navigationService,apiAutostradeManagerFactory)
{
OpenVideoWebcamCommand = new Command<Webcam>(async (webcam) => {
await navigationService.NavigateAsync(Locator.WebcamVideoPopUpPage);
Messenger.Default.Send(new InfoWebcamVideoMessage(webcam.c_mpr, webcam.c_uuid, webcam.t_str_vid));
});
InitializeWebcamsCommand = new Command(async () => await RunSafe(InitializeWebcams()));
InitializeWebcamsCommand.Execute(null);
cancellationTokenDownloadFrames = tokenSourceDownloadFrames.Token;
DownloadFramesTask = new Task(async () => {
cancellationTokenDownloadFrames.ThrowIfCancellationRequested();
while (true)
{
try
{
await DownloadAndSetWebcamImages();
await Task.Delay(2000);
if (cancellationTokenDownloadFrames.IsCancellationRequested)
{
// Clean up here, then...
cancellationTokenDownloadFrames.ThrowIfCancellationRequested();
}
}
catch (System.FormatException e)
{
Console.WriteLine(e.Message);
}
}
}, cancellationTokenDownloadFrames);
SetFrameOnViewTask = new Task(async () =>
{
cancellationTokenSetFrame.ThrowIfCancellationRequested();
while (true)
{
try
{
Counter++;
await Task.Delay(500);
if (cancellationTokenSetFrame.IsCancellationRequested)
{
Counter = 0;
// Clean up here, then...
cancellationTokenSetFrame.ThrowIfCancellationRequested();
}
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
}
}, cancellationTokenSetFrame);
}
private async Task InitializeWebcams()
{
folder = await FileSystem.Current.LocalStorage.GetFolderAsync("WebcamImages");
ListOfWebcam = await RepositoryHelper.Instance.WebcamRepository.GetItemsAsync();
ListOfWebcam = ListOfWebcam.OrderByDescending(x => x.n_prg_km).ToList();
try
{
if (DownloadFramesTask.Status == TaskStatus.Running)
{
try
{
tokenSourceDownloadFrames.Cancel();
}
finally
{
tokenSourceDownloadFrames.Dispose();
}
}
DownloadFramesTask.Start();
if (SetFrameOnViewTask.Status == TaskStatus.Running)
{
try
{
tokenSourceSetFrame.Cancel();
}
finally
{
tokenSourceSetFrame.Dispose();
}
}
SetFrameOnViewTask.Start();
}
catch (System.InvalidOperationException)
{}
}
private async Task DownloadAndSetWebcamImages()
{
await ImageService.Instance.InvalidateCacheAsync(CacheType.All);
foreach (var web in ListOfWebcam)
{
web.image1 = await GetWebcamFrame(web.frame1);
web.image2 = await GetWebcamFrame(web.frame2);
web.image3 = await GetWebcamFrame(web.frame3);
web.image4 = await GetWebcamFrame(web.frame4);
}
}
private async Task<ImageSource> GetWebcamFrame(string urlFrame)
{
try
{
var frameResponse = await ApiManager.GetWebcamFrame(urlFrame);
var base64Image = await frameResponse.Content.ReadAsStringAsync();
byte[] imageData = Convert.FromBase64String(base64Image);
return (ImageSource.FromStream(() => { return new MemoryStream(imageData); }));
}
catch (FormatException e)
{
throw e;
}
}
public class Webcam : INotifyPropertyChanged
{
[PrimaryKey, AutoIncrement]
public int idWebcam { get; set; }
public string c_mpr { get; set; }
public int c_tel { get; set; }
public string c_uuid { get; set; }
public string direzione { get; set; }
public string frame1 { get; set; }
public string frame2 { get; set; }
public string frame3 { get; set; }
public string frame4 { get; set; }
public double n_crd_lat { get; set; }
public double n_crd_lon { get; set; }
public int n_ind_pri { get; set; }
public double n_prg_km { get; set; }
public int ramo { get; set; }
public int str { get; set; }
public string strada { get; set; }
public string t_str_vid { get; set; }
public string thumb { get; set; }
public ImageSource image1 { get; set; }
public ImageSource image2 { get; set; }
public ImageSource image3 { get; set; }
public ImageSource image4 { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
在我的数据模板中,我用计数器绑定每个图像的isVisible
和isnabled
,通过四个转换器将其转换为布尔值。
我将只展示其中一个:
public class VisibleFrame1Converter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((int)value % 4 == 0)
return true;
else
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
例如,这一帧用于显示满足计数器条件时的第一帧。
我的模型类如下所示:
public class WebcamListViewModel : BaseViewModel
{
public ICommand InitializeWebcamsCommand { set; get; }
public ICommand OpenVideoWebcamCommand { set; get; }
private List<Webcam> _ListOfWebcam { get; set; }
public List<Webcam> ListOfWebcam
{
get { return _ListOfWebcam; }
set
{
_ListOfWebcam = value;
OnPropertyChanged();
}
}
private IFolder folder;
private int _Counter { get; set; }
public int Counter
{
get { return _Counter; }
set
{
_Counter = value;
OnPropertyChanged();
}
}
private Task SetFrameOnViewTask;
private Task DownloadFramesTask;
CancellationTokenSource tokenSourceSetFrame = new CancellationTokenSource();
CancellationTokenSource tokenSourceDownloadFrames = new CancellationTokenSource();
CancellationToken cancellationTokenSetFrame;
CancellationToken cancellationTokenDownloadFrames;
public WebcamListViewModel(INavigationService navigationService, IApiAutostradeManagerFactory apiAutostradeManagerFactory) : base(navigationService,apiAutostradeManagerFactory)
{
OpenVideoWebcamCommand = new Command<Webcam>(async (webcam) => {
await navigationService.NavigateAsync(Locator.WebcamVideoPopUpPage);
Messenger.Default.Send(new InfoWebcamVideoMessage(webcam.c_mpr, webcam.c_uuid, webcam.t_str_vid));
});
InitializeWebcamsCommand = new Command(async () => await RunSafe(InitializeWebcams()));
InitializeWebcamsCommand.Execute(null);
cancellationTokenDownloadFrames = tokenSourceDownloadFrames.Token;
DownloadFramesTask = new Task(async () => {
cancellationTokenDownloadFrames.ThrowIfCancellationRequested();
while (true)
{
try
{
await DownloadAndSetWebcamImages();
await Task.Delay(2000);
if (cancellationTokenDownloadFrames.IsCancellationRequested)
{
// Clean up here, then...
cancellationTokenDownloadFrames.ThrowIfCancellationRequested();
}
}
catch (System.FormatException e)
{
Console.WriteLine(e.Message);
}
}
}, cancellationTokenDownloadFrames);
SetFrameOnViewTask = new Task(async () =>
{
cancellationTokenSetFrame.ThrowIfCancellationRequested();
while (true)
{
try
{
Counter++;
await Task.Delay(500);
if (cancellationTokenSetFrame.IsCancellationRequested)
{
Counter = 0;
// Clean up here, then...
cancellationTokenSetFrame.ThrowIfCancellationRequested();
}
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
}
}, cancellationTokenSetFrame);
}
private async Task InitializeWebcams()
{
folder = await FileSystem.Current.LocalStorage.GetFolderAsync("WebcamImages");
ListOfWebcam = await RepositoryHelper.Instance.WebcamRepository.GetItemsAsync();
ListOfWebcam = ListOfWebcam.OrderByDescending(x => x.n_prg_km).ToList();
try
{
if (DownloadFramesTask.Status == TaskStatus.Running)
{
try
{
tokenSourceDownloadFrames.Cancel();
}
finally
{
tokenSourceDownloadFrames.Dispose();
}
}
DownloadFramesTask.Start();
if (SetFrameOnViewTask.Status == TaskStatus.Running)
{
try
{
tokenSourceSetFrame.Cancel();
}
finally
{
tokenSourceSetFrame.Dispose();
}
}
SetFrameOnViewTask.Start();
}
catch (System.InvalidOperationException)
{}
}
private async Task DownloadAndSetWebcamImages()
{
await ImageService.Instance.InvalidateCacheAsync(CacheType.All);
foreach (var web in ListOfWebcam)
{
web.image1 = await GetWebcamFrame(web.frame1);
web.image2 = await GetWebcamFrame(web.frame2);
web.image3 = await GetWebcamFrame(web.frame3);
web.image4 = await GetWebcamFrame(web.frame4);
}
}
private async Task<ImageSource> GetWebcamFrame(string urlFrame)
{
try
{
var frameResponse = await ApiManager.GetWebcamFrame(urlFrame);
var base64Image = await frameResponse.Content.ReadAsStringAsync();
byte[] imageData = Convert.FromBase64String(base64Image);
return (ImageSource.FromStream(() => { return new MemoryStream(imageData); }));
}
catch (FormatException e)
{
throw e;
}
}
public class Webcam : INotifyPropertyChanged
{
[PrimaryKey, AutoIncrement]
public int idWebcam { get; set; }
public string c_mpr { get; set; }
public int c_tel { get; set; }
public string c_uuid { get; set; }
public string direzione { get; set; }
public string frame1 { get; set; }
public string frame2 { get; set; }
public string frame3 { get; set; }
public string frame4 { get; set; }
public double n_crd_lat { get; set; }
public double n_crd_lon { get; set; }
public int n_ind_pri { get; set; }
public double n_prg_km { get; set; }
public int ramo { get; set; }
public int str { get; set; }
public string strada { get; set; }
public string t_str_vid { get; set; }
public string thumb { get; set; }
public ImageSource image1 { get; set; }
public ImageSource image2 { get; set; }
public ImageSource image3 { get; set; }
public ImageSource image4 { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
预期结果是在视图中显示下载的每一帧(我确定每一帧都已下载,我逐一检查),并每次下载更新版本。可能您的问题是网络摄像头。cs,还需要使用
INotifyPropertyChanged
作为其属性。详情如下:
public class Webcam : INotifyPropertyChanged
{
[PrimaryKey, AutoIncrement]
public int idWebcam { get; set; }
public string c_mpr { get; set; }
public int c_tel { get; set; }
public string c_uuid { get; set; }
public string direzione { get; set; }
public string frame1 { get; set; }
public string frame2 { get; set; }
public string frame3 { get; set; }
public string frame4 { get; set; }
public double n_crd_lat { get; set; }
public double n_crd_lon { get; set; }
public int n_ind_pri { get; set; }
public double n_prg_km { get; set; }
public int ramo { get; set; }
public int str { get; set; }
public string strada { get; set; }
public string t_str_vid { get; set; }
public string thumb { get; set; }
// modified code
ImageSource image1 ;
public ImageSource Image1
{
set
{
if (image1 != value)
{
image1 = value;
OnPropertyChanged("Image1");
}
}
get
{
return image1 ;
}
}
ImageSource image2 ;
public ImageSource Image2
{
set
{
if (image2 != value)
{
image2 = value;
OnPropertyChanged("Image2");
}
}
get
{
return image2 ;
}
}
ImageSource image3 ;
public ImageSource Image3
{
set
{
if (image3 != value)
{
image3 = value;
OnPropertyChanged("Image3");
}
}
get
{
return image3 ;
}
}
ImageSource image4 ;
public ImageSource Image4
{
set
{
if (image4 != value)
{
image4 = value;
OnPropertyChanged("Image4");
}
}
get
{
return image4 ;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
任何其他想要更新属性的,都需要在模型中使用
OnPropertyChanged
。只在WebCamListModel.cs
中使用,Webcam
的属性无法工作。您是否尝试过表单
,而不是使用ffimageloading:CachedImage
?是的,我尝试过,但得到了相同的结果。谢谢,这有点帮助。现在图像源已加载,但只是其中的一部分立即加载,列表的最后十个元素在一段时间后显示了它们的图像。@Giuseppennisi Okey,我认为并非所有图像都立即显示是正常现象。因为加载的图像需要时间,如果图像的大小较大,则需要更多的时间来加载它们。关于图像的加载延迟,这需要优化。您可以为其创建新问题。谢谢您的帮助。我提出了另一个关于代码优化的问题。这里的链接:@giusepeppennisi好的,我会检查它。@giuseppennisi对于大图像,图像可以被压缩和显示,而不会影响图片的清晰度。您还可以使用自定义渲染器在本机Android和iOS方法上加载图像,这将改善显示效果。