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

Xamarin 在TableView列表中更改as开关时,如何执行操作?,xamarin,xamarin.forms,Xamarin,Xamarin.forms,我们的应用程序显示类别组列表: 列出类别组; 在屏幕上,它看起来像这样: 运动23[打开] 5[打开] 国家55[开启] 职业0[关闭] 行对象如下所示: public类CategoryGroupWordCountVM:ObservableProperty{ 公共int Id{get;set;} 公共字符串名称{get;set;} 公共布尔值已切换{get;set;} } 第XAML页: 行XAML: 支持C# 受保护的无效刷新页(){ categoryGroups=App.DB.G

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

列出类别组;
在屏幕上,它看起来像这样:

运动23[打开]

5[打开]

国家55[开启]

职业0[关闭]

行对象如下所示:

public类CategoryGroupWordCountVM:ObservableProperty{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共布尔值已切换{get;set;}
}
第XAML页:


行XAML:


支持C#

受保护的无效刷新页(){
categoryGroups=App.DB.GetCategoryGroupWithWordCount();
var节=新表节(“可用类别”);
foreach(类别组中的变量类别){
var cell=newmyviewcell{BindingContext=category};
第.节添加(单元格);
}
tableView.Root.Add(节);
}
出现时受保护的覆盖无效(){
base.OnAppearing();
刷新页面();
}
我们想要做的是,当用户切换toggle时,调用如下方法,并更新切换所更改行的TotalWordCount值

void selectCategoryGroup(对象发送方,SelectedItemChangedEventArgs e){
如果(如SelectedItem==null){
返回;
}
var categoryGroup=(CategoryGroupWordCountVM)e.SelectedItem;
App.DB.UpdateCategoryGroupIsToggled(categoryGroup.IsToggled,categoryGroup.Id);
//接下来的行需要更新该值,以便
//屏幕在屏幕左侧显示的新值
//开关。当开关关闭时,它将始终处于关闭状态
//0.启用时,将显示类别中的单词列表
TotalWordCount=GetWordCountForCategory(categoryGroup.Id);
}
这是以前通过添加此代码实现的`


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

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


请注意,CategoryGroup列表中通常会有20-30个不同的条目。另外,如果它能让事情变得更简单,那么如果MyViewCell是用C#编码的,我会很高兴。

你可以订阅切换时引发的切换事件。

更新了08/21:重新构造了一点答案并添加了清理代码;添加了另一个基于属性更改事件的解决方案

选项1-使用自定义事件 为了在父级
表视图
级别处理开关的
切换
事件;您需要将事件传播到父viewcell。其中一种方法是在自定义的
MyViewCell
中公开事件

步骤:

  • 在自定义viewcell中声明事件(代码隐藏)

  • 并在其中调用自定义事件(在控件的代码隐藏中)

  • 用法:您现在可以在使用/实例化自定义viewcell的父页面中订阅自定义事件

    //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);
    }
    
  • 选择行为:您可以通过在
    ViewCell
    中处理
    Tapped
    事件并引发
    selectedorggled
    事件(类似于Handle_Toggled)来进一步自定义此行为,以模拟
    ListView
    选择行为

    选项2-在视图模型中使用
    PropertyChanged
    事件 您可以收听
    CategoryGroupWordCountVM
    中的
    IsToggled
    属性更改,并做出相应的反应

    步骤:

  • 用法:您可以在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
            ...
        }
    }
    
  • 清理:为避免内存泄漏,建议您在卸载期间取消订阅

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

  • 为什么在更改开关后再次创建TableView??您希望根据切换开关操作db,这没有问题,但是不需要调用方法RefreshPage(),因为视图已经更改。您可以给出一个示例吗。谢谢你非常好的回答。我对这个问题表示感谢,并接受了你的回答。我(或我工作的小组中的其他人)可能有更多类似这样的问题,非常感谢您的帮助。谢谢:)-很高兴知道这个答案有帮助。
    protected override void OnDisappearing()
    {
        base.OnDisappearing();
    
        foreach (var section in tableView.Root)
        {
            foreach(var cell in section)
            {
                cell.Tapped -= openCategoriesPage;
            }
        }
    }
    
    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
            ...
        }
    }
    
    protected override void OnDisappearing()
    {
        base.OnDisappearing();
    
        foreach (var section in tableView.Root)
        {
            foreach(var cell in section)
            {
                (cell as ObservableProperty)?.PropertyChanged -= CategoryVM_PropertyChanged;
            }
        }
    }