在TableView列表中更改开关时,我们如何执行操作?

时间:2017-08-18 04:14:31

标签: xamarin xamarin.forms

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

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

在屏幕上看起来像这样:

  

运动23 [开启]

     

爱好5 [开启]

     

国家55 [开启]

     

职业0 [关闭]

行对象如下:

<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>

Page 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>

行XAML:

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

支持C#

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

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

<ListView ItemSelected="selectCategoryGroup" >

之前通过添加此代码“

实现了这一点
{{1}}

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

所以我们非常感谢任何人都可以提供一些关于如何在更改开关时触发selectCategoryGroup等方法的建议。

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

2 个答案:

答案 0 :(得分:4)

更新时间:08/21: 重组后的答案并添加了清理代码;添加了基于属性更改事件

的其他解决方案

选项1 - 使用自定义事件

为了处理父Toggled级别的切换TableView事件;您需要将事件传播到父视单元。其中一种方法是在自定义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;
            }
        }
    }
    
  6. 选择行为:您可以通过处理Tapped中的ViewCell事件并提升SelectedOrToggled事件(类似于Handle_Toggled)来进一步自定义此事件,以便模仿{ {1}}选择行为。

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

    您可以在PropertyChanged中收听IsToggled属性更改并做出相应的反应。

    <强>步骤:

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

      PropertyChanged
    2. 清理:为避免内存泄漏,建议您在卸载期间取消订阅。

      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
              ...
          }
      }
      

答案 1 :(得分:2)

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