【问题标题】:How can we perform an action when as switch is changed in a TableView List?当 TableView 列表中的开关更改时,我们如何执行操作?
【发布时间】:2017-08-24 11:28:37
【问题描述】:

我们的应用程序显示类别组列表:

List<CategoryGroupWordCountVM> categoryGroups;

在屏幕上看起来像这样:

体育 23 [开启]

爱好 5 [开启]

国家 55 [开启]

职业 0 [关闭]

这样的行对象:

public class CategoryGroupWordCountVM : ObservableProperty {
   public int Id { get; set; }
   public string Name { get; set; }
   public bool IsToggled { get; set; }
}

页面 XAML:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Japanese;assembly=Japanese"        x:Class="Japanese.CategoryGroupPage" x:Name="CategoryGroupPage">
   <ContentPage.Content>
      <TableView x:Name="tableView" Intent="Settings">
      </TableView>
   </ContentPage.Content>
</ContentPage>

行 XAML:

<ViewCell 
   xmlns="http://xamarin.com/schemas/2014/forms" 
   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
   x:Class="Japanese.MyViewCell">
   <Grid>
      <Label Text = "{Binding Name}" />
      <Label Text = "{Binding TotalWordCount}" />
      <Switch IsToggled = "{Binding IsToggled}" />
   </Grid>
</ViewCell>

支持 C#

protected void RefreshPage() {
   categoryGroups = App.DB.GetCategoryGroupWithWordCount();
   var section = new TableSection("Available Categories");
   foreach (var category in categoryGroups) {
      var cell = new MyViewCell { BindingContext = category };
  section.Add(cell);
   }
   tableView.Root.Add(section);
}

protected override void OnAppearing() {
   base.OnAppearing();
   RefreshPage();
}

我们想要做的是,当用户切换切换时,会调用如下所示的方法,并更新切换更改所在行的 TotalWordCount 值。

void selectCategoryGroup(object sender, SelectedItemChangedEventArgs e) {
   if (e.SelectedItem == null) {
      return;
   }
   var categoryGroup = (CategoryGroupWordCountVM)e.SelectedItem;
   App.DB.UpdateCategoryGroupIsToggled(categoryGroup.IsToggled, categoryGroup.Id);
   // The row that follows needs to update the value so that 
   // the screen shows a new value for on the left side of 
   // the switch. When the switch is off this will always be
   // 0. When on it will be the list of words in the category
   TotalWordCount = GetWordCountForCategory(categoryGroup.Id);
}

这是以前通过添加此代码实现的 `

<ListView ItemSelected="selectCategoryGroup" >

但是现在我们使用的是 TableView,我们没有这个。

因此,如果有人能就如何在开关更改时触发 selectCategoryGroup 之类的方法提供一些建议,我们将不胜感激。

请注意,categoryGroups 列表中通常会有大约 20-30 个不同的条目。另外,如果 MyViewCell 是用 C# 编码的,我会很高兴。

【问题讨论】:

  • 为什么更改开关后又要创建TableView??你想根据拨动开关来操作db,没问题,但是不需要调用RefreshPage()方法,因为视图已经改变了。

标签: xamarin xamarin.forms


【解决方案1】:

于 08/21 更新: 稍微调整了答案并添加了清理代码;添加了另一个基于属性更改事件的解决方案

选项 1 - 使用自定义事件

为了在父级TableView 处理开关的Toggled 事件;您需要将事件传播到父视单元。其中一种方法是在您的自定义 MyViewCell 中公开一个事件。

步骤:

  1. 在您的自定义视图单元中声明事件(代码隐藏)。

    public event EventHandler<SelectedItemChangedEventArgs> SelectedOrToggled;
    
  2. 为 viewcell 的 XAML 中定义的开关分配 Toggled 事件处理程序

    <ViewCell 
        xmlns="http://xamarin.com/schemas/2014/forms" 
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
        x:Class="Japanese.MyViewCell">
        <Grid>
            <Label Text = "{Binding Name}" />
            <Label Text = "{Binding TotalWordCount}" />
            <Switch IsToggled = "{Binding IsToggled}" Toggled="Handle_Toggled" />
        </Grid>   
    
  3. 并在其中调用您的自定义事件(在控件的代码隐藏中)

    void Handle_Toggled(object sender, Xamarin.Forms.ToggledEventArgs e)
    {
        var view = sender as BindableObject;
        SelectedOrToggled?.Invoke(this, new 
        SelectedItemChangedEventArgs(view.BindingContext));
    }
    
  4. 用法:您现在可以在使用/实例化自定义视单元的父页面中订阅自定义事件。

    //XAML usage
    //<local:MyViewCell SelectedOrToggled="selectCategoryGroup" />
    
    protected void RefreshPage()
    {
        categoryGroups = App.DB.GetCategoryGroupWithWordCount();
        var section = new TableSection("Available Categories");
        foreach (var category in categoryGroups)
        {
            var cell = new MyViewCell { BindingContext = category };
            // assign method as event-handler
            cell.SelectedOrToggled += selectCategoryGroup;
            section.Add(cell);
        }
        tableView.Root.Add(section);
    }
    
  5. 清理:为避免内存泄漏,建议您在卸载期间取消订阅。

    protected override void OnDisappearing()
    {
        base.OnDisappearing();
    
        foreach (var section in tableView.Root)
        {
            foreach(var cell in section)
            {
                cell.Tapped -= openCategoriesPage;
            }
        }
    }
    

选择行为:您可以通过处理ViewCell 中的Tapped 事件并引发SelectedOrToggled 事件(类似于Handle_Toggled)来进一步自定义此行为,以模仿ListView 选择行为。

选项 2 - 在视图模型中使用 PropertyChanged 事件

您可以在CategoryGroupWordCountVM 中收听IsToggled 的属性变化并做出相应的反应。

步骤:

  1. 用法:您可以在viewmodel中订阅PropertyChanged事件。

    protected void RefreshPage()
    {
        categoryGroups = App.DB.GetCategoryGroupWithWordCount();
        var section = new TableSection("Available Categories");
        foreach (var category in categoryGroups)
        {
            var cell = new MyViewCell { BindingContext = category };
            // assign method as event-handler
            cat.PropertyChanged += CategoryVM_PropertyChanged;
            section.Add(cell);
        }
        tableView.Root.Add(section);
    }
    
    async void CategoryVM_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName == nameof(CategoryGroupWordCountVM.IsToggled))
        {
            var categoryGroup = (CategoryGroupWordCountVM)sender;
            ...//call update code here
            ...
        }
    }
    
  2. 清理:为避免内存泄漏,建议您在卸载期间取消订阅。

    protected override void OnDisappearing()
    {
        base.OnDisappearing();
    
        foreach (var section in tableView.Root)
        {
            foreach(var cell in section)
            {
                (cell as ObservableProperty)?.PropertyChanged -= CategoryVM_PropertyChanged;
            }
        }
    }
    

【讨论】:

  • 感谢您非常好的回答。为了表示感谢,我为这个问题开辟了一个赏金,并接受了你的回答。我(或我工作的小组中的其他人)可能有更多这样的问题,非常感谢您的帮助。
  • 谢谢 :) - 很高兴知道这个答案有帮助。
【解决方案2】:

您可以订阅 Switch 的 Toggled 事件,该事件在 Switch 切换时引发。

【讨论】:

  • 你能举个例子吗。谢谢
猜你喜欢
  • 2012-06-03
  • 1970-01-01
  • 2021-06-24
  • 1970-01-01
  • 2021-12-28
  • 2020-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多