英文:
How to refresh data in view model in MAUI app
问题
我在XAML文件中有一个轮播视图:
<CarouselView x:Name="AttView" ItemsSource="{Binding Attendances}" IndicatorView="indicatorView">
<CarouselView.ItemTemplate>
<DataTemplate x:DataType="model:AttendanceItem">
<Grid Margin="0, 20, 0, 0"
ColumnDefinitions="*, *"
RowDefinitions="Auto, Auto, Auto, Auto, Auto">
<Label Margin="0, 5, 0, 5" Grid.Row="0" Grid.Column="0" Text="Turno actual" />
<Label Margin="0, 5, 0, 5" Grid.Row="0" Grid.Column="1" Text="{Binding TurnoActual}" />
<Label Margin="0, 5, 0, 5" Grid.Row="1" Grid.Column="0" Text="Hora de llegada" />
<Label Margin="0, 5, 0, 5" Grid.Row="1" Grid.Column="1" Text="{Binding HoraLlegada, StringFormat='{0:HH:mm}'}" />
<Label Margin="0, 5, 0, 5" Grid.Row="2" Grid.Column="0" Text="Hora de salida" />
<Label Margin="0, 5, 0, 5" Grid.Row="2" Grid.Column="1" Text="{Binding HoraSalida, StringFormat='{0:HH:mm}'}" />
<Label Margin="0, 5, 0, 5" Grid.Row="3" Grid.Column="0" Text="Horas trabajadas" />
<Label Margin="0, 5, 0, 5" Grid.Row="3" Grid.Column="1" Text="{Binding HorasTrabajadas, StringFormat='{0:hh} h {0:mm} m'}" />
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView x:Name="indicatorView"
IndicatorColor="Gray"
SelectedIndicatorColor="Black"
HorizontalOptions="Center" />
另一方面,视图模型定义如下:
public ObservableCollection<AttendanceItem> Attendances { get; set; }
public MainViewModel()
{
Attendances = new ObservableCollection<AttendanceItem>
{
new AttendanceItem
{
TurnoActual = new TurnoItem
{
Inicio = DateTime.Today.AddHours(8),
Fin = DateTime.Today.AddHours(18),
Tipo = Enums.TipoTurnoEnum.Fijo
},
HoraLlegada = DateTime.Today.AddHours(7).AddMinutes(50)
}
};
}
最后,这是集合的项目:
public class AttendanceItem
{
public TurnoItem TurnoActual { get; set; }
public DateTime? HoraLlegada { get; set; }
public DateTime? HoraSalida { get; set; }
public TimeSpan HorasTrabajadas {
get {
if (HoraLlegada is null && HoraSalida is null)
return TimeSpan.Zero;
DateTime llegada = HoraLlegada ?? DateTime.Today.Add(TurnoActual.Inicio.TimeOfDay);
DateTime salida = HoraSalida ?? DateTime.Now;
return salida - llegada;
}
}
}
请注意 HorasTrabajadas
属性。如果 HoraSalida
为 null,则应显示当前时间。
所以问题是,如何刷新视图,以便我可以看到 HorasTrabajadas
属性每隔1分钟增加其值?
我尝试在视图的代码后台使用计时器,使用以下代码:
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
OnPropertyChanged(nameof(MainViewModel.Attendances));
}
但是它没有起作用。
英文:
I have a carousel view in a XAML file:
<CarouselView x:Name="AttView" ItemsSource="{Binding Attendances}" IndicatorView="indicatorView">
<CarouselView.ItemTemplate>
<DataTemplate x:DataType="model:AttendanceItem">
<Grid Margin="0, 20, 0, 0"
ColumnDefinitions="*, *"
RowDefinitions="Auto, Auto, Auto, Auto, Auto">
<Label Margin="0, 5, 0, 5" Grid.Row="0" Grid.Column="0" Text="Turno actual" />
<Label Margin="0, 5, 0, 5" Grid.Row="0" Grid.Column="1" Text="{Binding TurnoActual}" />
<Label Margin="0, 5, 0, 5" Grid.Row="1" Grid.Column="0" Text="Hora de llegada" />
<Label Margin="0, 5, 0, 5" Grid.Row="1" Grid.Column="1" Text="{Binding HoraLlegada, StringFormat='{0:HH:mm}'}" />
<Label Margin="0, 5, 0, 5" Grid.Row="2" Grid.Column="0" Text="Hora de salida" />
<Label Margin="0, 5, 0, 5" Grid.Row="2" Grid.Column="1" Text="{Binding HoraSalida, StringFormat='{0:HH:mm}'}" />
<Label Margin="0, 5, 0, 5" Grid.Row="3" Grid.Column="0" Text="Horas trabajadas" />
<Label Margin="0, 5, 0, 5" Grid.Row="3" Grid.Column="1" Text="{Binding HorasTrabajadas, StringFormat='{0:hh} h {0:mm} m'}" />
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView x:Name="indicatorView"
IndicatorColor="Gray"
SelectedIndicatorColor="Black"
HorizontalOptions="Center" />
On the other hand, the viewmodel is defined this way:
public ObservableCollection<AttendanceItem> Attendances { get; set; }
public MainViewModel()
{
Attendances = new ObservableCollection<AttendanceItem>
{
new AttendanceItem
{
TurnoActual = new TurnoItem
{
Inicio = DateTime.Today.AddHours(8),
Fin = DateTime.Today.AddHours(18),
Tipo = Enums.TipoTurnoEnum.Fijo
},
HoraLlegada = DateTime.Today.AddHours(7).AddMinutes(50)
}
};
}
And finally, this is the item of the collection:
public class AttendanceItem
{
public TurnoItem TurnoActual { get; set; }
public DateTime? HoraLlegada { get; set; }
public DateTime? HoraSalida { get; set; }
public TimeSpan HorasTrabajadas {
get {
if (HoraLlegada is null && HoraSalida is null)
return TimeSpan.Zero;
DateTime llegada = HoraLlegada ?? DateTime.Today.Add(TurnoActual.Inicio.TimeOfDay);
DateTime salida = HoraSalida ?? DateTime.Now;
return salida - llegada;
}
}
}
Notice HorasTrabajadas
property. If HoraSalida
is null, current time should be displayed.
So the question is, how can I refresh the view so that I can see how the HorasTrabajadas
property increments its value every 1 minute?
I tried with a timer in the view code behind, with this code:
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
OnPropertyChanged(nameof(MainViewModel.Attendances));
}
But it did not work.
答案1
得分: 0
Jason指出了,Mode AttendanceItem必须实现INotifyPropertyChanged
接口,而.NET MAUI中的数据绑定机制会将处理程序附加到此PropertyChanged
事件,以便在属性更改时收到通知并将目标更新为新值。
你可以参考以下示例代码:
public class AttendanceItem : INotifyPropertyChanged
{
private DateTime horaLlegada;
public DateTime HoraLlegada
{
get => horaLlegada;
set
{
if (horaLlegada != value)
{
horaLlegada = value;
OnPropertyChanged("HoraLlegada");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
更多信息,请参考数据绑定和MVVM。
英文:
As Jason has pointed it out that the Mode AttendanceItem must implement INotifyPropertyChanged
interface and the data binding mechanism in .NET MAUI attaches a handler to this PropertyChanged
event so it can be notified when a property changes and keep the target updated with the new value.
You can refer to the sample code below:
public class AttendanceItem: INotifyPropertyChanged
{
private DateTime horaLlegada;
public DateTime HoraLlegada
{
get => horaLlegada;
set
{
if (horaLlegada != value)
{
horaLlegada = value;
OnPropertyChanged("HoraLlegada");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propName = null)
{
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(propName));
}
}
For more information, you can refer to Data binding and MVVM.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论