C# 如何在image.source中为listView的每个元素定期设置图像?

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

我需要在ListView的每个查看器中设置从rest服务获取的图像。这些图像会定期更改以创建“gif”效果,一段时间后,我会调用该服务以获取有关网络摄像头的更新图像。问题是并不是所有的图像都被设置,只是其中的一部分,有时甚至没有一个图像被设置

我的代码如下:

 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方法上加载图像,这将改善显示效果。