繁体   English   中英

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

[英]How to set periodically image in image.source for each element of a listView?

我需要设置图像以从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;
        }
    }

在我的viewModel中,我有两个任务: DownloadFramesTaskSetFrameOnViewTask ,每500毫秒增加一个计数器,该计数器用于显示转弯处的四个帧之一。

<ListView ItemsSource="{Binding ListOfWebcam}"
              SeparatorVisibility="None"
              CachingStrategy="RetainElement"
              RowHeight="250"
              VerticalOptions="FillAndExpand"
              x:Name="ListWebcam">

        <ListView.Header>
            <StackLayout x:Name="HeaderStackLayout"
                               Padding="5,25,0,30"
                               Orientation="Horizontal"
                               HorizontalOptions="FillAndExpand">

                    <Label  x:Name="LabelHeader"
                              Text="Webcam:"
                              FontSize="Large"
                              FontAttributes="Bold"
                              TextColor="{x:Static statics:Palette.PrimaryColor}"
                              VerticalOptions="Center"
                              HorizontalOptions="Start" Margin="10,0,0,0"/>
            </StackLayout>
        </ListView.Header>

        <ListView.ItemTemplate>
            <DataTemplate>

                <controls:ExtendedViewCell SelectedItemBackgroundColor="#fafafa">

                    <Grid x:Name="GridWebcam">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>

                        <Frame Grid.Column="1"
                                   Grid.RowSpan="2"
                                   CornerRadius="20"
                                   BackgroundColor="{x:Static statics:Palette.PrimaryColor}"
                                   VerticalOptions="FillAndExpand"
                                   HorizontalOptions="FillAndExpand"
                                   HasShadow="True"
                                   Margin="5,10">

                            <StackLayout>

                                <Label Text="{Binding t_str_vid,Converter={StaticResource WebcamNameConverter}}"
                                           FontSize="Medium"
                                           TextColor="White"
                                           FontAttributes="Bold"
                                           HorizontalOptions="FillAndExpand"
                                           VerticalOptions="FillAndExpand">

                                </Label>

                                <Label TextColor="White"
                                           FontSize="Medium"
                                           Text="{Binding direzione,Converter={StaticResource DirectionToStringConverter}}"/>

                                <StackLayout Orientation="Horizontal">
                                    <ffimageloading:CachedImage DownsampleToViewSize="True"
                                                                VerticalOptions="FillAndExpand"
                                                                HorizontalOptions="StartAndExpand"
                                                                IsVisible="{Binding Source={x:Reference WebcamList},Path=BindingContext.Counter,Converter={StaticResource VisibleFrame1Converter}}"
                                                                IsEnabled="{Binding Source={x:Reference WebcamList},Path=BindingContext.Counter,Converter={StaticResource VisibleFrame1Converter}}"
                                                                Source="{Binding image1}"/>
                                    <ffimageloading:CachedImage x:Name="SecondFrame"
                                                                DownsampleToViewSize="True"
                                                                Grid.Row="1"
                                                                Grid.Column="0"
                                                                IsVisible="{Binding Source={x:Reference WebcamList},Path=BindingContext.Counter,Converter={StaticResource VisibleFrame2Converter}}"
                                                                IsEnabled="{Binding Source={x:Reference WebcamList},Path=BindingContext.Counter,Converter={StaticResource VisibleFrame2Converter}}"

                                                                VerticalOptions="FillAndExpand"
                                                                HorizontalOptions="StartAndExpand"
                                                                Source="{Binding image2}"/>

                                    <ffimageloading:CachedImage x:Name="ThirdFrame"
                                                                Grid.Row="1"
                                                                Grid.Column="0"

                                                                IsVisible="{Binding Source={x:Reference WebcamList},Path=BindingContext.Counter,Converter={StaticResource VisibleFrame3Converter}}"
                                                                IsEnabled="{Binding Source={x:Reference WebcamList},Path=BindingContext.Counter,Converter={StaticResource VisibleFrame3Converter}}"

                                                                VerticalOptions="FillAndExpand"
                                                                HorizontalOptions="StartAndExpand"
                                                                Source="{Binding image3}"/>

                                    <ffimageloading:CachedImage x:Name="FourthFrame"
                                                                Grid.Row="1"
                                                                Grid.Column="0"
                                                                IsVisible="{Binding Source={x:Reference WebcamList},Path=BindingContext.Counter,Converter={StaticResource VisibleFrame4Converter}}"
                                                                IsEnabled="{Binding Source={x:Reference WebcamList},Path=BindingContext.Counter,Converter={StaticResource VisibleFrame4Converter}}"

                                                                VerticalOptions="FillAndExpand"
                                                                HorizontalOptions="StartAndExpand"
                                                                Source="{Binding image4}"/>

                                    <iconize:IconButton Text="fas-play-circle"
                                                            FontSize="50"
                                                            HorizontalOptions="EndAndExpand"
                                                            VerticalOptions="EndAndExpand"
                                                            TextColor="White"
                                                            Command="{Binding BindingContext.OpenVideoWebcamCommand, Source={x:Reference ListWebcam}}"
                                                            CommandParameter="{Binding}"
                                                            BackgroundColor="Transparent"/>
                                </StackLayout>
                            </StackLayout>
                        </Frame>
                    </Grid>
                </controls:ExtendedViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

在我的dataTemplate中,我将每个图像的isVisibleisEnabled与计数器绑定,这要归功于四个转换器,将其转换为布尔值。 我只显示其中之一:

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 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));
    }
}

预期的结果是在视图中显示下载的每个帧(我确定每个帧都已下载,我已逐一检查),并每隔一段时间都下载更新的版本。

也许您的问题是Webcam.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在Model.Just在WebcamListViewModel.cs使用, Webcam的属性不能正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM