【问题标题】:How can I stop a Toggled Event on a switch from being fired as a page is loaded?如何在加载页面时阻止开关上的切换事件被触发?
【发布时间】:2018-01-30 23:10:18
【问题描述】:

我的应用程序在 XAML 和后端 C# 代码中设置了一个开关来响应切换事件

<ViewCell x:Name="ss">
   <Switch x:Name="ssSwitch" Toggled="SsSwitch"   />
</ViewCell>

void SsSwitch(object sender, ToggledEventArgs e) {
    // Code to update database here
}

页面首次加载时,我注意到调用了 SwSwitch Toggled 事件。

有什么方法可以阻止这种情况的发生,因为没有理由在启动时更新数据库。

【问题讨论】:

  • 如果你有一个加载标志,你可以在响应切换操作之前确保视图实际上已经完成加载......
  • 如果您使用 MVVM 模式 - 您可以使用 PropertyChanged 事件或属性设置器来检测值更新(而不是切换事件)。可以在此答案中找到一个示例stackoverflow.com/a/41071201/7292772

标签: xamarin xamarin.forms


【解决方案1】:

选项 1:在 ViewModel 中使用属性设置器

如果您使用 MVVM - 解决此问题的最简单选项是使用属性设置器 来检测值更新(如 link 中所述)。但是如果你想在这里调用可等待的方法,这个选项不起作用。此外,作为最佳实践,建议属性不应实现any time consuming operations

bool _isToggled;
public bool IsToggled 
{ 
    get 
    {
        return _isToggled;
    } 
    set
    {
        _isToggled = value;
        // Add your update code here
    }
}

选项 2:在 ViewModel 中使用 PropertyChanged 事件

下一个选项是在您的视图模型中订阅PropertyChanged 事件并适当地处理它。这允许您定义异步处理程序,这些处理程序反过来可以等待异步方法。

// 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();
    }
}

选项 3:在 ViewCell 中覆盖 OnAppearing()

另一种选择是确保在BindingContextViewCell 上更新之后分配Toggled 事件处理程序。所以,我做了一个快速的实验来跟踪在加载视图时调用Handle_ToggledOnBindingContextChangedOnAppearing 方法的顺序。原来顺序是:

Handle_Toggled
OnBindingContextChanged
OnAppearing

因此,OnAppearing 方法中分配处理程序(在 ViewCell 的代码隐藏中)也应该适用于这种情况:

//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");
}

这样Handle_Toggled只会在用户切换开关时被调用。

【讨论】:

    【解决方案2】:

    Switch 上方的代码不应在首次启动时触发事件。仅当您将 IsToggled 属性与 ViewModel 绑定时才会触发!这样做的原因是,首先初始化 Page,ViewModel 切换 Switch,然后触发事件。

    第一个解决方案是从代码隐藏处理 IsToggled 属性和 Toggled 事件(如果您正在对代码进行 mvvm-ing,则不建议这样做)。更好的解决方案是从 ViewModel 处理两者。

    问题是,Switch 控件没有Command 属性。您必须使用行为绑定到Command. Sharada Gururaj 已经在上面发布了一个链接,并提供了很好的解释。

    这里是 Sharada Gururajs stackoverflow 的简短解决方案链接:Xamarin Forms Switch Toggled event doesn't bind with viewmodel

    <Switch IsToggled="{Binding IsToggled}">
    <Switch.Behaviors>
        <behaviors:EventHandlerBehavior EventName="Toggled">
        <behaviors:InvokeCommandAction Command="{Binding ToggleSwitchCommand}" />
        </behaviors:EventHandlerBehavior>
    </Switch.Behaviors>
    

    更多信息:

    【讨论】:

      猜你喜欢
      • 2013-01-01
      • 1970-01-01
      • 2011-02-06
      • 1970-01-01
      • 2014-05-04
      • 2012-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多