ListView с индикатором выполнения, заполненным свойством Model - PullRequest
0 голосов
/ 17 февраля 2019

Уважаемые,

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

Мой взгляд:

   <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="H2XA.View.PatientView"
             Title="Pacientes">

        <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">

            <Label x:Name="Paciente1" Text="Paciente"
                   HorizontalOptions="Center"
                   VerticalOptions="Center"
                    />  
              <ListView x:Name="Patients" 
                          ItemSelected="OnSelection"
                          IsPullToRefreshEnabled="True">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <ViewCell.ContextActions>
                                    <MenuItem Text="Renomear" CommandParameter="{Binding .}"
                                         Clicked="Renomear_Clicked" />
                                </ViewCell.ContextActions>
                                <StackLayout Padding="5,0,5,0">
                                    <Label Text="{Binding Name}" Font="16"/>
                                    <Label Text="{Binding Medidas}" Font="14" />
                                    <ProgressBar ProgressColor="{Binding Bar_Color}" 
                                     Progress="{Binding CurrentProgress}" 
                                     PropertyChanged="ProgressBar_PropertyChanged"/>
                                </StackLayout>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackLayout>

</ContentPage>

и

 public partial class PatientView : ContentPage
    {
        public PatientView()
        {
            InitializeComponent();

            BindingContext = App.PVM;
            Patients.ItemsSource = App.PVM.AllPatient;
        }
        private async void OnSelection(object sender, SelectedItemChangedEventArgs e)
        {
            if (e.SelectedItem == null)
            {
                return;
            }
            await DisplayAlert("Selecionado", e.SelectedItem.ToString(), "Ok");
            string a = e.SelectedItem.ToString().Substring(0, 12);

        }

        private void Renomear_Clicked(object sender, EventArgs e)
        {
            //replace name
            var item = (MenuItem)sender;
            (item.CommandParameter as Patient).Name = "new name";

        }


        private void ProgressBar_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
        //This is the way that i found.
        var item = (sender as ProgressBar) ;

        if(item.Progress==0)
        item.ProgressTo(1, 15000, Easing.Linear);

        if (item.Progress == 1)
        item.ProgressColor = Color.Green;

        }
    }

Этоспособ, которым я нахожу, чтобы заполнить мой список ProgressBars в объекты.Но ему не нравится хороший способ реализации решения, потому что я не могу контролировать время моего ProgressBar, и ослабление «Линейного» не совсем линейно для больших чисел.

Первый параметр ProgressTo - это Progress,что я хочу показать в момент, когда я установил его вместе в параметре secound.

Я хотел бы внедрить его в мою модель в качестве параметра моего объекта.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using H2XA.ViewModel;
using Xamarin.Forms;

namespace H2XA.Model
{
    public class Patient:INotifyPropertyChanged
    {
        public Guid Id { get; set; }
        public DateTime examdate;
        public int cronometro;
        public decimal barCronometro;
        public Color Bar_Color;
        private string name;
        private string medidas;

        public Patient()
        {
            cronometro = 0;

            Device.StartTimer(TimeSpan.FromSeconds(15),  () =>
            {
                if (cronometro < 6)
                {
                    Bar_Color = Color.Blue;
                    cronometro++;
                }
                else
                {

                    if (cronometro == 60)
                    {
                        Bar_Color = Color.Red;
                    }
                }


                CurrentProgress = (cronometro / 60);


                return true;
            });

        }

        private decimal _currentProgress;
        public decimal CurrentProgress
        {
            get { return _currentProgress; }
            private set
            {
                _currentProgress = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                OnPropertyChanged();//Esse comando faz a tela ser atualizada quando algo é inserido.

            }
        }
        public string Medidas
        {
            get { return medidas; }
            set
            {
                medidas = value;
               OnPropertyChanged();//Esse comando faz a tela ser atualizada quando algo é inserido.

            }
        }

    }
}

Но когда ясделайте это таким образом, чтобы анимация отсутствовала, и не обновляйте время на рисунке, только когда закончите время, когда сработает приговор, и моя полоса окажется заполненной.Я не знаю, хорошо ли работает моя привязка, и для меня я сделал кое-что, что имеет смысл.

Я проверяю код и замечаю, что мой ProgressBar_PropertyChanged вызывается каждый раз, и это не очень хорошо для моей эффективности в приложениях.,Может ли кто-нибудь помочь мне улучшить мой код и организовать мою функцию, чтобы лучше организовать мой проект MVVM.

Заранее спасибо

Guilherme Marques

1 Ответ

0 голосов
/ 19 февраля 2019
  1. Когда ProgressBar не в ListView .Вам следует Переопределить режим привязки , режим привязки по умолчанию для целевого свойства равен OneWay. Когда данные вашей модели изменились, прогресс выполнения установлен там. Это не так.вызвать этот метод ProgressTo.

Здесь вы должны использовать режим привязки TwoWay, он будет отображаться правильно.

Пример кода следующим образом:

Xaml:

 <ProgressBar x:Name="progressBar" 
                     Progress="{Binding CurrentProgress,Mode=TwoWay}" 
                     PropertyChanged="ProgressBar_PropertyChanged"/>

ContentPage: При изменении данных модели он будет работать.

private void ProgressBar_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            //This is the way that i found.
            var item = (sender as ProgressBar);

            //if (item.Progress == 0)
                item.ProgressTo(1, 15000, Easing.Linear);

            //if (item.Progress == 1)
                //item.ProgressColor = Color.Green;

        }

И вы можете удалить ProgressBar_PropertyChanged Метод. Когда данные изменились, выполните следующие действия:

   dataModel.CurrentProgress = 0.8;
   ...
   progressBar.ProgressTo(dataModel.CurrentProgress, 3000, Easing.Linear);
Когда ProgressBar связан в ListView с MVVM , это не может произойти Animation. Вот статья для справки.

Решение:

Ниже приведен метод использования Timer для запланированных задач для изменения данных хода выполнения.

Timer timer; // create a timer
DataModel dataModel; // data model
private double ApiProgressData = 0; // Simulate data from Api

Таймер инициализации и его обработчик событий:

 timer = new Timer();
 timer.Interval = 100;
 timer.Elapsed += Timer_Elapsed;

  private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {   
        if (ApiProgressData > dataModel.CurrentProgress)
        {
            dataModel.CurrentProgress = dataModel.CurrentProgress + 0.01;
            if ((ApiProgressData - dataModel.CurrentProgress) < 0.00001)
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    timer.Stop();
                });

            }
        }
        else if (ApiProgressData < dataModel.CurrentProgress)
        {
            dataModel.CurrentProgress = dataModel.CurrentProgress - 0.01;
            if (( dataModel.CurrentProgress - ApiProgressData ) < 0.00001)
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    timer.Stop();
                });

            }
        }else{
            Device.BeginInvokeOnMainThread(() =>
                {
                    timer.Stop();
                });
        }
    }

После изменения данных Api используйте таймер для изменения данных модели:

 ApiProgressData = 0.8; //  Simulate data is 0.8 to test
 timer.Start();

Или вы можете попробовать использовать стороннюю библиотеку, какупоминается в статье выше.

...