如何在 MAUI 应用中刷新视图模型中的数据

huangapple go评论111阅读模式
英文:

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:

     &lt;CarouselView x:Name=&quot;AttView&quot; ItemsSource=&quot;{Binding Attendances}&quot; IndicatorView=&quot;indicatorView&quot;&gt;
        &lt;CarouselView.ItemTemplate&gt;
            &lt;DataTemplate x:DataType=&quot;model:AttendanceItem&quot;&gt;
                &lt;Grid Margin=&quot;0, 20, 0, 0&quot; 
                          ColumnDefinitions=&quot;*, *&quot; 
                          RowDefinitions=&quot;Auto, Auto, Auto, Auto, Auto&quot;&gt;
                    &lt;Label Margin=&quot;0, 5, 0, 5&quot; Grid.Row=&quot;0&quot; Grid.Column=&quot;0&quot; Text=&quot;Turno actual&quot; /&gt;
                    &lt;Label Margin=&quot;0, 5, 0, 5&quot; Grid.Row=&quot;0&quot; Grid.Column=&quot;1&quot; Text=&quot;{Binding TurnoActual}&quot; /&gt;
                    &lt;Label Margin=&quot;0, 5, 0, 5&quot; Grid.Row=&quot;1&quot; Grid.Column=&quot;0&quot; Text=&quot;Hora de llegada&quot; /&gt;
                    &lt;Label Margin=&quot;0, 5, 0, 5&quot; Grid.Row=&quot;1&quot; Grid.Column=&quot;1&quot; Text=&quot;{Binding HoraLlegada, StringFormat=&#39;{0:HH:mm}&#39;}&quot; /&gt;
                    &lt;Label Margin=&quot;0, 5, 0, 5&quot; Grid.Row=&quot;2&quot; Grid.Column=&quot;0&quot; Text=&quot;Hora de salida&quot; /&gt;
                    &lt;Label Margin=&quot;0, 5, 0, 5&quot; Grid.Row=&quot;2&quot; Grid.Column=&quot;1&quot; Text=&quot;{Binding HoraSalida, StringFormat=&#39;{0:HH:mm}&#39;}&quot; /&gt;
                    &lt;Label Margin=&quot;0, 5, 0, 5&quot; Grid.Row=&quot;3&quot; Grid.Column=&quot;0&quot; Text=&quot;Horas trabajadas&quot; /&gt;
                    &lt;Label Margin=&quot;0, 5, 0, 5&quot; Grid.Row=&quot;3&quot; Grid.Column=&quot;1&quot; Text=&quot;{Binding HorasTrabajadas, StringFormat=&#39;{0:hh} h {0:mm} m&#39;}&quot; /&gt;
                &lt;/Grid&gt;
            &lt;/DataTemplate&gt;
        &lt;/CarouselView.ItemTemplate&gt;
    &lt;/CarouselView&gt;
    &lt;IndicatorView x:Name=&quot;indicatorView&quot;
               IndicatorColor=&quot;Gray&quot;
               SelectedIndicatorColor=&quot;Black&quot;
               HorizontalOptions=&quot;Center&quot; /&gt;

On the other hand, the viewmodel is defined this way:

public ObservableCollection&lt;AttendanceItem&gt; Attendances { get; set; }

public MainViewModel()
{
    Attendances = new ObservableCollection&lt;AttendanceItem&gt;
    {
        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 &amp;&amp; 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 =&gt; horaLlegada;
         set
         {
             if (horaLlegada != value)
             {
                    horaLlegada = value;
                    OnPropertyChanged(&quot;HoraLlegada&quot;);
              }
         }

    }

        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.

huangapple
  • 本文由 发表于 2023年6月8日 05:01:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76427088.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定