如何在Xamarin Forms中单独在ListView的所有项目中运行StartTimer

时间:2017-04-11 10:16:37

标签: listview xamarin.forms

我正在尝试为5个城市运行时钟,例如列表视图的每个单元格中的每个城市和运行除城市名称之外的时钟(本地时间)。 (下面的截图)

我使用该城市的偏移值获取城市的当地时间。

为了移动时钟,我使用了StartTimer,因此时间每秒都会改变。

目前我将offsetValue设为零,因此所有城市的UTC时间都相同。

我希望当地时间的所有城市都显示在城市名称旁边,时钟必须每秒都移动一次。

任何帮助将不胜感激.. 提前谢谢。

Sample screenshot of cities with respective clocks

List<OffsetItems> items = new List<OffsetItems>();
        items.Add(new OffsetItems() { CityName = "Hyderabad", Offset = 5.5 });
        items.Add(new OffsetItems() { CityName = "London", Offset = 1 });
        items.Add(new OffsetItems() { CityName = "Tokyo", Offset = 9 });
        items.Add(new OffsetItems() { CityName = "New York", Offset = -5 });
        items.Add(new OffsetItems() { CityName = "Dubai", Offset = 4 });


        ListView lv = new ListView
        {
            SeparatorVisibility = SeparatorVisibility.None,
            ItemsSource = items,

            ItemTemplate = new DataTemplate(() =>
            {

                Label cityL = new Label()
                {
                    TextColor = Color.Black,
                    HorizontalTextAlignment = TextAlignment.Start,
                    FontSize = Device.GetNamedSize(NamedSize.Small, new Label())
                };
                Label timeL = new Label()
                {
                    TextColor = Color.Black,
                    HorizontalTextAlignment = TextAlignment.Center,
                    FontSize = Device.GetNamedSize(NamedSize.Small, new Label())
                };
                cityL.SetBinding<OffsetItems>(Label.TextProperty, indexer => indexer.CityName);

                Label ll = new Label();
                Device.StartTimer(TimeSpan.FromSeconds(1), () => {

                    ll.SetBinding<OffsetItems>(Label.TextProperty, indexer => indexer.Offset);
                    double offsetValue = Convert.ToDouble(ll.Text);

                    timeL.Text = DateTime.UtcNow.AddHours(offsetValue).ToString("hh:mm:ss tt, ddd dd-MMM-yyyy");
                    return true; 
                });

                return new ViewCell
                {
                    View = new StackLayout
                    {
                        Orientation = StackOrientation.Horizontal,
                        Children =
                            {
                            cityL,
                            timeL
                        }
                    }
                };
            })
        };

        Content = new StackLayout
        {
            Children = {
                lv
            }
        };

2 个答案:

答案 0 :(得分:0)

我认为你的模板中不应该有StartTimer。你应该在OnAppearing方法中有一个StartTimer(例如)。

当StartTimer事件上升时,您应该更改&#34; Time&#34;你应该在你的模型中拥有的属性(将&#34;时间&#34;属性更改为ObservableCollection中的所有项目......你不应该使用&#34; List&#34;)。绑定这个&#34;时间&#34;属于你的&#34; timeL&#34;领域。现在,如果实现INotifyPropertyChanged,则timeL字段应自动更新。

答案 1 :(得分:0)

我已经添加了Alessandro所提到的代码,以及它应该如何完成。

class OffsetItems : INotifyPropertyChanged
    {
        private double _offset;
        private string _time;
        private string _cityName;

        public string CityName
        {
            get { return _cityName; }
            internal set
            {
                _cityName = value;
                OnPropertyChanged("CityName");
            }
        }

        public string Time
        {
            get { return _time; }
            internal set
            {
                _time = value;
                OnPropertyChanged("Time");
            }
        }

        public double Offset
        {
            get { return _offset; }
            internal set
            {
                _offset = value;
                OnPropertyChanged("Offset");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public partial class MainPage : ContentPage
    {
        ObservableCollection<OffsetItems> Items = new ObservableCollection<OffsetItems>();

        public MainPage()
        {
            InitializeComponent();

            Items.Add(new OffsetItems() { CityName = "Hyderabad", Offset = 5.5 });
            Items.Add(new OffsetItems() { CityName = "London", Offset = 1 });
            Items.Add(new OffsetItems() { CityName = "Tokyo", Offset = 9 });
            Items.Add(new OffsetItems() { CityName = "New York", Offset = -5 });
            Items.Add(new OffsetItems() { CityName = "Dubai", Offset = 4 });

            var lv = new ListView
            {
                ItemsSource = Items,
                SeparatorVisibility = SeparatorVisibility.None,
                ItemTemplate = new DataTemplate(() =>
                {

                    Label cityL = new Label()
                    {
                        TextColor = Color.Black,
                        HorizontalTextAlignment = TextAlignment.Start,
                        FontSize = Device.GetNamedSize(NamedSize.Small, new Label())
                    };
                    Label timeL = new Label()
                    {
                        TextColor = Color.Black,
                        HorizontalTextAlignment = TextAlignment.Center,
                        FontSize = Device.GetNamedSize(NamedSize.Small, new Label())
                    };
                    cityL.SetBinding<OffsetItems>(Label.TextProperty, indexer => indexer.CityName);
                    timeL.SetBinding<OffsetItems>(Label.TextProperty, indexer => indexer.Time, BindingMode.OneWay);

                    Label ll = new Label();

                    return new ViewCell
                    {
                        View = new StackLayout
                        {
                            Orientation = StackOrientation.Horizontal,
                            Children =
                            {
                                cityL,
                                timeL
                            }
                        }
                    };
                })
            };

            Content = new StackLayout
            {
                Children = {
                    lv
                }
            };
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            Device.StartTimer(TimeSpan.FromSeconds(1), () =>
            {
                Items.ForEach(row => row.Time = DateTime.UtcNow.AddHours(row.Offset)
                    .ToString("hh:mm:ss tt, ddd dd-MMM-yyyy"));
                return true;
            });
        }
    }

* Foreach是我在私有lib中的扩展。希望这段代码有帮助