Mi aplicación tiene un interruptor configurado en XAML y un código C # de backend que responde al evento de alternancia
<ViewCell x:Name="ss">
<Switch x:Name="ssSwitch" Toggled="SsSwitch" />
</ViewCell>
void SsSwitch(object sender, ToggledEventArgs e) {
// Code to update database here
}
Cuando la página se carga por primera vez, noto que se llama al evento SwSwitch Toggled.
¿Hay alguna forma de evitar que esto suceda ya que no hay razón para hacer una actualización de la base de datos al inicio?
Respuestas
1 para la respuesta № 1Opción 1: utilizar el configurador de propiedades en ViewModel
Si está utilizando MVVM, la opción más simple para resolver esto sería usar establecedor de propiedades para detectar la actualización de valor (como se menciona en este enlazar) Pero esta opción no funciona si desea llamar a métodos pendientes aquí. Además, como práctica recomendada, se recomienda que las propiedades no se implementen operaciones que requieren mucho tiempo.
bool _isToggled;
public bool IsToggled
{
get
{
return _isToggled;
}
set
{
_isToggled = value;
// Add your update code here
}
}
Opción 2: uso PropertyChanged
evento en ViewModel
La siguiente opción sería Suscribirse a PropertyChanged
evento en su modelo de vista y manejarlo adecuadamente. Esto le permite definir manejadores asíncronos que a su vez pueden esperar métodos asincrónicos.
// Subscribe to event while constructing/assigning viewmodel
// viewCellVM.PropertyChanged += CategoryVM_PropertyChanged;
async void ViewCellVM_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(e.PropertyName == nameof(ViewCellVM.IsToggled))
{
//call update code here
//await DB.Update();
}
}
Opción 3: anulación OnAppearing()
en ViewCell
Otra opción es asegurarse de que el Toggled
el controlador de eventos se asigna después de BindingContext
se actualiza en el ViewCell
. Entonces, hice un experimento rápido para rastrear el pedido Handle_Toggled
, OnBindingContextChanged
, OnAppearing
se llaman a los métodos mientras se carga la vista. El orden resultó ser:
Handle_Toggled
OnBindingContextChanged
OnAppearing
Por lo tanto, asignando el manejador en OnAppearing
El método (en el código subyacente de ViewCell) también debería funcionar para este caso:
//XAML:<Switch x:Name="switchBtn" IsToggled="{Binding IsToggled}" />
protected override void OnAppearing()
{
base.OnAppearing();
switchBtn.Toggled += Handle_Toggled;
Debug.WriteLine("OnAppearing");
}
protected override void OnDisappearing()
{
base.OnDisappearing();
switchBtn.Toggled -= Handle_Toggled;
Debug.WriteLine("OnDisappearing");
}
De esta manera Handle_Toggled
solo se llamará cuando el usuario cambie el interruptor.
1 para la respuesta № 2
Con su código arriba del Switch
no debería activar el evento en el primer inicio. Solo se activa si ha vinculado su IsToggled
propiedad con su ViewModel! La razón de esto es que la página se inicializa primero, el modelo de vista cambia el interruptor y luego se activa el evento.
La primera solución sería manejar el IsToggled
propiedad y el Toggled
evento ambos del código subyacente (no recomendado si está mvvm-ing su código). Una mejor solución sería manejar ambos desde ViewModel.
El problema es que el Switch
El control no tiene Command
propiedad. Tienes que usar un comportamiento para enlazar a un Command.
Sharada Gururaj ya publicó un enlace arriba con una buena explicación.
Aquí está la solución corta del enlace de stackoverflow de Sharada Gururaj: Xamarin Forms Switch Toggled event no enlaza con viewmodel
<Switch IsToggled="{Binding IsToggled}">
<Switch.Behaviors>
<behaviors:EventHandlerBehavior EventName="Toggled">
<behaviors:InvokeCommandAction Command="{Binding ToggleSwitchCommand}" />
</behaviors:EventHandlerBehavior>
</Switch.Behaviors>
Más información:
- https://blog.xamarin.com/turn-events-into-commands-with-behaviors/
- https://forums.xamarin.com/discussion/64374/switch-with-istoggled-binding-is-throwing-toggled-event-on-init-when-bound-value-is-true