【问题标题】:Xamarin Timer crashesXamarin 计时器崩溃
【发布时间】:2022-01-06 03:20:00
【问题描述】:

所以我已经在代码中完成了这个:

public partial class Timer : ContentView , INotifyPropertyChanged
    {
        private int seconds = 30;
        
        private System.Timers.Timer timer;
        public Timer()
        {
            InitializeComponent();
            timer = new System.Timers.Timer();
            timer.Interval = 1000;
            timer.AutoReset = true;
            timer.Elapsed += new System.Timers.ElapsedEventHandler(OneSecondPassed);
            timer.Enabled = true;
        }
        private void OneSecondPassed(object source, System.Timers.ElapsedEventArgs e)
        {
            seconds--;
            Time = seconds.ToString();
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public string Time
        {
            get => seconds.ToString();
            set
            {
                Time = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this ,  new PropertyChangedEventArgs("Time"));
                }
                
            }   
        }
    }

然后在 XAML 中将我的标签文本绑定到它:

 <Label  BindingContext ="{x:Reference this}"
              Text="{Binding Time}"/>

当我启动应用程序时,它崩溃了......我真的不明白 PropertyChanged 是如何工作的,只是 INotifyPropertyChanged 实现了它。另外,当我声明 PropertyChanged 时,它告诉我 BindableObject.PropertyChanged 已经存在,使用 new in为了隐藏它。如果您能解释界面及其事件的工作原理,我将非常感谢。

【问题讨论】:

  • 什么是异常/错误消息?
  • 您可能需要使用Dispatcher 更改Text 属性的值,否则绑定在错误的线程上运行,也许是ThreadPool? Timer documentation。可以通过将 Timer 的 SynchronizingObject 设置为 this 来缓解?

标签: c# xamarin xamarin.forms


【解决方案1】:

你的 setter 正在创建一个无限循环。

set
{
   // this will call the setter again, infinitely
   Time = value;
   ...
}

你已经有一个 seconds 的私有变量,你应该在这里使用它

public int Time
    {
        get => seconds;
        set
        {
            seconds = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this ,  new PropertyChangedEventArgs("Time"));
            }
            
        }   
    }

private void OneSecondPassed(object source, System.Timers.ElapsedEventArgs e)
{
   Time--;
}

【讨论】:

  • 我希望 Time 属性为字符串类型,这样我就可以将标签的文本绑定到它...所以我不能真正做 Time--;
  • 当然可以。您可以将 int 绑定到标签 - .NET 会自动为您转换它。
  • 标签仍然保持不变...有什么想法吗?
  • 我只想说 label.text = seconds--.ToString() 每秒而不是使用绑定..
  • 只要 UI 线程上发生更新,绑定就应该可以工作
【解决方案2】:

当我声明 PropertyChanged 时,它告诉我 BindableObject.PropertyChanged 已经存在

我看到Timer 继承自ContentView。

ContentView 是一个BindableObject,因此它已经实现了绑定中使用的所有内容,例如 PropertyChanged。删除PropertyChanged的声明。


可选:您也可以删除 , INotifyPropertyChanged - ContentView 会为您执行此操作。不过放在那里也无害。

【讨论】:

  • 哦,很高兴知道!这很令人困惑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多