秒表列表 - 由于绑定,重新启动开始所有计时器
List of Stopwatches - restarting begins all timers due to binding
希望您能提供帮助...我有一个活动列表,这些活动使用秒表来跟踪每个 activity 持续时间。当我点击列表中的 activity 时,它会启动所点击的 activity 的秒表,当我再次点击 activity 行时,它会停止并重置秒表。
然而,当我点击另一个 activity 时,虽然它实际上只是更新在后端点击的 activity 的持续时间,但前端 UI 会更新所有活动计时器具有相同的 activity 时间,因为它们绑定到相同的 activityduration 元素。我不知道如何只更改前端点击的 activity 的 activity 持续时间。如果没有 re-structuring 我的 model/collection,谁能建议如何做到这一点?还是我必须在 collection 中为 activity 名称创建一个子嵌套?
隐藏代码中的点击事件:-
public async void OnActivityTap(object sender, EventArgs e)
{
var item = (ViewCell)sender;
UserActivities.Activities myactivitiesModel = item.BindingContext as UserActivities.Activities;
if (myactivitiesModel == null)
{return;}
// OnPropertyChanged("ActivityDuration");
// mystopwatch.Reset();
//ViewModel.getUserActivities();
foreach (var x in ViewModel.UserActivitiesList) {
if(x.ActivityName == myactivitiesModel.ActivityName) {
int seconds = 1;
//if the activity is not enabled and the activity is tapped
if (myactivitiesModel.ActivityEnabled == false)
{
//enable the activity and start the stopwatch
myactivitiesModel.ActivityEnabled = true;
//Get the current duration and add it onto the stopwatch start time
ts = x.ActivityDuration;
//Reset the stopwatch back to zero
mystopwatch = new Stopwatch();
//Start the stopwatch
mystopwatch.Reset();
mystopwatch.Start();
while (myactivitiesModel.ActivityEnabled == true)
{
Device.StartTimer(TimeSpan.FromSeconds(seconds), () =>
{
myactivitiesModel.ActivityDuration = (mystopwatch.Elapsed + ts);
return true;
});
return;
}
}
else if (myactivitiesModel.ActivityEnabled == true)
{
//disable the activity and stop the stopwatch
x.ActivityEnabled = false;
//Stop the clock
mystopwatch.Stop();
//Store activity time stopped
await MongoService.UpdateUserActivityTime(userIdentity, myactivitiesModel.ActivityName, x.ActivityDuration);
//Store the time stopped in the UserActivitiesList binded to the UI list
x.ActivityDuration = myactivitiesModel.ActivityDuration;
OnPropertyChanged("ActivityDuration");
return;
}
} //end of if activityName Tapped
} //end of foreach
} //end of OnTap Activity
型号:
public class UserActivities : INotifyPropertyChanged
{
[BsonId, BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
string _foreignUserID;
[BsonElement("foreignUserID")]
public string foreignUserID
{
get => _foreignUserID; set
{
if (_foreignUserID == value)
return;
_foreignUserID = value;
HandlePropertyChanged();
}
}
[BsonElement("activities")]
public ObservableCollection<Activities> UserTimedActivities { get; set; }
public class Activities : INotifyPropertyChanged
{
string _activityName;
[BsonElement("activityName")]
public string ActivityName
{
get => _activityName; set
{
if (_activityName == value)
return;
_activityName = value;
HandlePropertyChanged();
}
}
TimeSpan _activityDuration;
[BsonElement("activityDuration")]
public TimeSpan ActivityDuration
{
get => _activityDuration; set
{
if (_activityDuration == value)
return;
_activityDuration = value;
HandlePropertyChanged();
}
}
TimeSpan _activityGoalDuration;
[BsonElement("activityGoalDuration")]
public TimeSpan ActivityGoalDuration
{
get => _activityGoalDuration; set
{
if (_activityGoalDuration == value)
return;
_activityGoalDuration = value;
HandlePropertyChanged();
}
}
Boolean _activityEnabled;
[BsonElement("activityEnabled")]
public Boolean ActivityEnabled
{
get => _activityEnabled; set
{
if (_activityEnabled == value)
return;
_activityEnabled = value;
HandlePropertyChanged();
}
}
public Activities(string activityname, TimeSpan activityduration, TimeSpan activitygoalduration, Boolean activityenabled ) {
ActivityName = activityname;
ActivityDuration = activityduration;
ActivityGoalDuration = activitygoalduration;
ActivityEnabled = activityenabled;
}
void HandlePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public UserActivities(ObservableCollection<Activities> usertimedactivities)
{
UserTimedActivities = usertimedactivities;
}
public event PropertyChangedEventHandler PropertyChanged;
void HandlePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
ViewModel方法编译列表-
public async void getUserActivities()
{
var userActivities = await MongoService.GetUserActivityData(userIdentity);
try
{
if (IsBusy)
return;
IsBusy = true;
UserActivitiesList.Clear();
foreach (var x in userActivities)
{
foreach(var y in x.UserTimedActivities) {
//foreach (var y in x.userActivities)
UserActivitiesList.Add(y);
}
}
}
catch (Exception ex)
{
IsBusy = false;
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
2。 Jason 建议的替代计时器方法(不获取经过时间或更新 UI):
public async void OnActivityTap(object sender, EventArgs e)
{
var item = (ViewCell)sender;
UserActivities.Activities myactivitiesModel = item.BindingContext as UserActivities.Activities;
if (myactivitiesModel == null)
{ return; }
foreach (var x in ViewModel.UserActivitiesList)
{
if (x.ActivityName == myactivitiesModel.ActivityName)
{
if (x.ActivityEnabled == false)
{
x.ActivityEnabled = true;
timer.Enabled = true;
timer.Start();
timer.Elapsed += OnTimedEvent;
x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
else
{
x.ActivityEnabled = false;
timer.Enabled = false;
timer.Stop();
x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
**3。使用秒表的替代方法 - 确实有效但不会更新 UI 直到点击 **
foreach (var x in ViewModel.UserActivitiesList)
{
if (x.ActivityName == myactivitiesModel.ActivityName)
{
if (x.ActivityEnabled == false)
{
x.ActivityEnabled = true;
//timer.Enabled = true;
mystopwatch.Restart();
mystopwatch.Start();
x.ActivityDuration = mystopwatch.Elapsed + x.ActivityDuration;
NotifyPropertyChanged("ActivityDuration");
//timer.Elapsed += OnTimedEvent;
//x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
else
{
x.ActivityEnabled = false;
//timer.Enabled = false;
mystopwatch.Stop();
x.ActivityDuration = mystopwatch.Elapsed + x.ActivityDuration;
NotifyPropertyChanged("ActivityDuration");
//x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
我认为你把这种方式搞得太复杂了。我会创建一个计时器并做这样的事情
using System.Timers;
...
// 100ms == .1s
double interval = 100;
// CREATE ONE TIMER FOR ALL ACTIVITIES
Timer timer = new Timer(interval);
timer.Elapsed += UpdateTimers;
timer.Start();
...
private void UpdateTimers(object sender, EventArgs a)
{
// this is psudocode, update for your model
foreach(var a in Activities)
{
// if activity is selected
if (a.Active) {
// update the elapsed time
a.Elapsed = a.Elapsed.Add(new Timespan(0,0,0,0,interval));
}
}
}
OP
实施的最终解决方案
public page()
{
timer.Start();
timer.Elapsed += UpdateTimers;
}
private void UpdateTimers(object sender, EventArgs a)
{
foreach (var x in ViewModel.UserActivitiesList)
{
if (x.ActivityEnabled)
{
x.ActivityDuration = x.ActivityDuration.Add(new
TimeSpan(0, 0, 0, 0, (int)interval));
}
}
}
希望您能提供帮助...我有一个活动列表,这些活动使用秒表来跟踪每个 activity 持续时间。当我点击列表中的 activity 时,它会启动所点击的 activity 的秒表,当我再次点击 activity 行时,它会停止并重置秒表。
然而,当我点击另一个 activity 时,虽然它实际上只是更新在后端点击的 activity 的持续时间,但前端 UI 会更新所有活动计时器具有相同的 activity 时间,因为它们绑定到相同的 activityduration 元素。我不知道如何只更改前端点击的 activity 的 activity 持续时间。如果没有 re-structuring 我的 model/collection,谁能建议如何做到这一点?还是我必须在 collection 中为 activity 名称创建一个子嵌套?
隐藏代码中的点击事件:-
public async void OnActivityTap(object sender, EventArgs e)
{
var item = (ViewCell)sender;
UserActivities.Activities myactivitiesModel = item.BindingContext as UserActivities.Activities;
if (myactivitiesModel == null)
{return;}
// OnPropertyChanged("ActivityDuration");
// mystopwatch.Reset();
//ViewModel.getUserActivities();
foreach (var x in ViewModel.UserActivitiesList) {
if(x.ActivityName == myactivitiesModel.ActivityName) {
int seconds = 1;
//if the activity is not enabled and the activity is tapped
if (myactivitiesModel.ActivityEnabled == false)
{
//enable the activity and start the stopwatch
myactivitiesModel.ActivityEnabled = true;
//Get the current duration and add it onto the stopwatch start time
ts = x.ActivityDuration;
//Reset the stopwatch back to zero
mystopwatch = new Stopwatch();
//Start the stopwatch
mystopwatch.Reset();
mystopwatch.Start();
while (myactivitiesModel.ActivityEnabled == true)
{
Device.StartTimer(TimeSpan.FromSeconds(seconds), () =>
{
myactivitiesModel.ActivityDuration = (mystopwatch.Elapsed + ts);
return true;
});
return;
}
}
else if (myactivitiesModel.ActivityEnabled == true)
{
//disable the activity and stop the stopwatch
x.ActivityEnabled = false;
//Stop the clock
mystopwatch.Stop();
//Store activity time stopped
await MongoService.UpdateUserActivityTime(userIdentity, myactivitiesModel.ActivityName, x.ActivityDuration);
//Store the time stopped in the UserActivitiesList binded to the UI list
x.ActivityDuration = myactivitiesModel.ActivityDuration;
OnPropertyChanged("ActivityDuration");
return;
}
} //end of if activityName Tapped
} //end of foreach
} //end of OnTap Activity
型号:
public class UserActivities : INotifyPropertyChanged
{
[BsonId, BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
string _foreignUserID;
[BsonElement("foreignUserID")]
public string foreignUserID
{
get => _foreignUserID; set
{
if (_foreignUserID == value)
return;
_foreignUserID = value;
HandlePropertyChanged();
}
}
[BsonElement("activities")]
public ObservableCollection<Activities> UserTimedActivities { get; set; }
public class Activities : INotifyPropertyChanged
{
string _activityName;
[BsonElement("activityName")]
public string ActivityName
{
get => _activityName; set
{
if (_activityName == value)
return;
_activityName = value;
HandlePropertyChanged();
}
}
TimeSpan _activityDuration;
[BsonElement("activityDuration")]
public TimeSpan ActivityDuration
{
get => _activityDuration; set
{
if (_activityDuration == value)
return;
_activityDuration = value;
HandlePropertyChanged();
}
}
TimeSpan _activityGoalDuration;
[BsonElement("activityGoalDuration")]
public TimeSpan ActivityGoalDuration
{
get => _activityGoalDuration; set
{
if (_activityGoalDuration == value)
return;
_activityGoalDuration = value;
HandlePropertyChanged();
}
}
Boolean _activityEnabled;
[BsonElement("activityEnabled")]
public Boolean ActivityEnabled
{
get => _activityEnabled; set
{
if (_activityEnabled == value)
return;
_activityEnabled = value;
HandlePropertyChanged();
}
}
public Activities(string activityname, TimeSpan activityduration, TimeSpan activitygoalduration, Boolean activityenabled ) {
ActivityName = activityname;
ActivityDuration = activityduration;
ActivityGoalDuration = activitygoalduration;
ActivityEnabled = activityenabled;
}
void HandlePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public UserActivities(ObservableCollection<Activities> usertimedactivities)
{
UserTimedActivities = usertimedactivities;
}
public event PropertyChangedEventHandler PropertyChanged;
void HandlePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
ViewModel方法编译列表-
public async void getUserActivities()
{
var userActivities = await MongoService.GetUserActivityData(userIdentity);
try
{
if (IsBusy)
return;
IsBusy = true;
UserActivitiesList.Clear();
foreach (var x in userActivities)
{
foreach(var y in x.UserTimedActivities) {
//foreach (var y in x.userActivities)
UserActivitiesList.Add(y);
}
}
}
catch (Exception ex)
{
IsBusy = false;
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
2。 Jason 建议的替代计时器方法(不获取经过时间或更新 UI):
public async void OnActivityTap(object sender, EventArgs e)
{
var item = (ViewCell)sender;
UserActivities.Activities myactivitiesModel = item.BindingContext as UserActivities.Activities;
if (myactivitiesModel == null)
{ return; }
foreach (var x in ViewModel.UserActivitiesList)
{
if (x.ActivityName == myactivitiesModel.ActivityName)
{
if (x.ActivityEnabled == false)
{
x.ActivityEnabled = true;
timer.Enabled = true;
timer.Start();
timer.Elapsed += OnTimedEvent;
x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
else
{
x.ActivityEnabled = false;
timer.Enabled = false;
timer.Stop();
x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
**3。使用秒表的替代方法 - 确实有效但不会更新 UI 直到点击 **
foreach (var x in ViewModel.UserActivitiesList)
{
if (x.ActivityName == myactivitiesModel.ActivityName)
{
if (x.ActivityEnabled == false)
{
x.ActivityEnabled = true;
//timer.Enabled = true;
mystopwatch.Restart();
mystopwatch.Start();
x.ActivityDuration = mystopwatch.Elapsed + x.ActivityDuration;
NotifyPropertyChanged("ActivityDuration");
//timer.Elapsed += OnTimedEvent;
//x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
else
{
x.ActivityEnabled = false;
//timer.Enabled = false;
mystopwatch.Stop();
x.ActivityDuration = mystopwatch.Elapsed + x.ActivityDuration;
NotifyPropertyChanged("ActivityDuration");
//x.ActivityDuration = x.ActivityDuration.Add(new TimeSpan(0, 0, 0, 0, (int)interval)); //new
return;
}
我认为你把这种方式搞得太复杂了。我会创建一个计时器并做这样的事情
using System.Timers;
...
// 100ms == .1s
double interval = 100;
// CREATE ONE TIMER FOR ALL ACTIVITIES
Timer timer = new Timer(interval);
timer.Elapsed += UpdateTimers;
timer.Start();
...
private void UpdateTimers(object sender, EventArgs a)
{
// this is psudocode, update for your model
foreach(var a in Activities)
{
// if activity is selected
if (a.Active) {
// update the elapsed time
a.Elapsed = a.Elapsed.Add(new Timespan(0,0,0,0,interval));
}
}
}
OP
实施的最终解决方案public page()
{
timer.Start();
timer.Elapsed += UpdateTimers;
}
private void UpdateTimers(object sender, EventArgs a)
{
foreach (var x in ViewModel.UserActivitiesList)
{
if (x.ActivityEnabled)
{
x.ActivityDuration = x.ActivityDuration.Add(new
TimeSpan(0, 0, 0, 0, (int)interval));
}
}
}