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

11 xamarin xamarin.forms

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

List<CategoryGroupWordCountVM> categoryGroups;
Run Code Online (Sandbox Code Playgroud)

在屏幕上它看起来像这样:

运动23 [开启]

爱好5 [开启]

国家55 [开启]

职业0 [关闭]

行对象如下:

public class CategoryGroupWordCountVM : ObservableProperty {
   public int Id { get; set; }
   public string Name { get; set; }
   public bool IsToggled { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

页面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>
Run Code Online (Sandbox Code Playgroud)

行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>
Run Code Online (Sandbox Code Playgroud)

支持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();
}
Run Code Online (Sandbox Code Playgroud)

我们想要做的是,当用户切换切换时,调用如下方法,并更新交换机更改的行的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);
}
Run Code Online (Sandbox Code Playgroud)

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

<ListView ItemSelected="selectCategoryGroup" >
Run Code Online (Sandbox Code Playgroud)

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

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

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

Sha*_*raj 3

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

选项 1 - 使用自定义事件

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

脚步:

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

    public event EventHandler<SelectedItemChangedEventArgs> SelectedOrToggled;
    
    Run Code Online (Sandbox Code Playgroud)
  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>   
    
    Run Code Online (Sandbox Code Playgroud)
  3. 并在其中调用您的自定义事件(在控件的代码隐藏中)

    void Handle_Toggled(object sender, Xamarin.Forms.ToggledEventArgs e)
    {
        var view = sender as BindableObject;
        SelectedOrToggled?.Invoke(this, new 
        SelectedItemChangedEventArgs(view.BindingContext));
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 清理:为避免内存泄漏,建议您在卸载期间取消订阅。

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

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

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

您可以监听IsToggled属性变化CategoryGroupWordCountVM并做出相应反应。

脚步:

  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
            ...
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 清理:为避免内存泄漏,建议您在卸载期间取消订阅。

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

  • 谢谢:) - 很高兴知道这个答案有帮助。 (2认同)