xamarin 如何在sfListView中对复选框进行分组和绑定?

xzabzqsa  于 2022-12-07  发布在  其他
关注(0)|答案(1)|浏览(166)

我有一个ObeservableCollection作为数据绑定到列表视图。下面是列表的示例:

[{"Category":"ENGINE","Key":"BATTERY","Value":"BATTERY"},
{"Category":"BRAKE","Key":"BRAKE","Value":"BRAKE PAD"}, 
{"Category":"ENGINE","Key":"COOLANT","Value":"COOLANT & WATER"}]

我已经实现的是类似下面的截图:
清单检视

是的,我可以使用组描述符根据模型中的一个属性对它们进行分组,还可以通过右侧的复选框将数据模板分配给GroupHeaderTemplate。
然而,问题是我不能通过调用id或name来访问组复选框,因为它是动态创建的。
我的要求是将组(黑色)和子项(粉红色)复选框链接在一起,这意味着当属于该组的所有子项都被选中时,组复选框也应自动选中,反之亦然。一旦其中一个项被取消选中,则组复选框也应被取消选中。
目前卡住了,不知道如何进行,任何帮助都将不胜感激。谢谢~
编辑代码:分组检查表.xaml

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"
xmlns:data="clr-namespace:Syncfusion.DataSource;assembly=Syncfusion.DataSource.Portable"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:ASolute_Mobile" xmlns:local1="clr-namespace:ASolute_Mobile.Models.GroupedCheckListModel" xmlns:button="clr-namespace:Syncfusion.XForms.Buttons;assembly=Syncfusion.Buttons.XForms"
x:Class="ASolute_Mobile.FleetScreen.GroupedCheckList">
    <StackLayout x:Name="Fleet_CheckItem" Spacing="15" Padding="15,15,15,15">          
        <syncfusion:SfListView x:Name="groupedListView" ItemsSource="{Binding Check}" AllowGroupExpandCollapse="True">
            <syncfusion:SfListView.DataSource>
                <data:DataSource>
                    <data:DataSource.GroupDescriptors>
                        <data:GroupDescriptor PropertyName="Category">
                        </data:GroupDescriptor>
                    </data:DataSource.GroupDescriptors>
                    </data:DataSource>
            </syncfusion:SfListView.DataSource>
            <syncfusion:SfListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            <StackLayout>
                                <StackLayout>
                                    <button:SfCheckBox Text="{Binding Name}" IsChecked="{Binding IsSelected}" CheckedColor="LightCoral"  FontSize="20" StateChanged="CheckBox_StateChanged" />
                                </StackLayout>                           
                            </StackLayout>                                
                        </ViewCell.View>
                    </ViewCell>
                </DataTemplate>
            </syncfusion:SfListView.ItemTemplate>
        </syncfusion:SfListView>
    <Image Source="nextPage.png" WidthRequest="70" HeightRequest="70" VerticalOptions="Center" HorizontalOptions="End" x:Name="fleet_confirm_icon" IsVisible="false">
        <Image.GestureRecognizers>
            <TapGestureRecognizer Tapped="fleet_toNextPage" />
        </Image.GestureRecognizers>
    </Image>
</StackLayout>
</ContentPage>

分组检查表. xaml.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using ASolute.Mobile.Models;
using ASolute_Mobile.Models;
using ASolute_Mobile.Models.GroupedCheckListModel;
using ASolute_Mobile.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Syncfusion.XForms.Buttons;
using Xamarin.Forms;

namespace ASolute_Mobile.FleetScreen
{
    public partial class GroupedCheckList : ContentPage
    {
        private ListItems item;
        string recordURL;
        List<clsCheckListItem> checkItems = new 
List<clsCheckListItem>();
    bool shouldLeave = true;

    public GroupedCheckList()
    {
        InitializeComponent();

        shouldLeave = false;

        StackLayout main = new StackLayout();

        Label title1 = new Label
        {
            FontSize = 15,
            Text = "Check List",
            TextColor = System.Drawing.Color.White
        };
        Label title2 = new Label
        {
            FontSize = 10,
            Text = Ultis.Settings.SubTitle,
            TextColor = System.Drawing.Color.White
        };

        main.Children.Add(title1);
        main.Children.Add(title2);

        NavigationPage.SetTitleView(this, main);
        NavigationPage.SetHasBackButton(this, false);

        displayData();
    }

    public GroupedCheckList(ListItems items, string recordUri)
    {

        item = items;
        InitializeComponent();

        shouldLeave = true;

        recordURL = recordUri;
        StackLayout main = new StackLayout();

        Label title1 = new Label
        {
            FontSize = 15,
            Text = "Check List",
            TextColor = System.Drawing.Color.White
        };
        Label title2 = new Label
        {
            FontSize = 10,
            Text = Ultis.Settings.SubTitle,
            TextColor = System.Drawing.Color.White
        };

        main.Children.Add(title1);
        main.Children.Add(title2);

        NavigationPage.SetTitleView(this, main);

        GetData();
    }

    async void GetData()
    {
        try
        {
            var content = await DependencyService.Get<CommonFunctionInterface>().CallWebService(0, null, Ultis.Settings.SessionBaseURI, recordURL, this);

            if (content != null)
            {
                clsResponse response = JsonConvert.DeserializeObject<clsResponse>(content);
                if (response.Result != "")
                {
                    var msgBoxResponse = await DisplayAlert("Info", response.Result, "YES", "NO");
                    if (msgBoxResponse)
                    {
                        displayData();
                    }
                    else
                    {
                        await Navigation.PopAsync();
                    }
                }
                else
                {
                    displayData();
                }
            }
        }
        catch (Exception e)
        {
            await DisplayAlert("Error", e.Message, "OK");
        }

    }

    async void displayData()
    {
        try
        {
            var content1 = await DependencyService.Get<CommonFunctionInterface>().CallWebService(0, null, Ultis.Settings.SessionBaseURI, ControllerUtil.getNewFleetCheckListURL(), this);
            if (content1 != null)
            {
                clsResponse response1 = JsonConvert.DeserializeObject<clsResponse>(content1);
                if (response1.IsGood == true)
                {
                    checkItems = JObject.Parse(content1)["Result"].ToObject<List<clsCheckListItem>>();
                    BindingContext = new GroupedCheckListModel(checkItems);
                    groupedListView.GroupHeaderTemplate = new DataTemplate(() => {
                        StackLayout headerStack = new StackLayout
                        {
                            Orientation = StackOrientation.Horizontal,
                            HorizontalOptions = LayoutOptions.FillAndExpand
                        };
                        StackLayout labelStack = new StackLayout
                        {
                            HorizontalOptions = LayoutOptions.StartAndExpand,                            
                        };
                        Label label = new Label()
                        {
                            FontSize = 22,
                            FontAttributes = FontAttributes.Bold
                        };
                        //Key is the property group.Key, not from our list
                        label.SetBinding(Label.TextProperty, "Key");
                        labelStack.Children.Add(label);
                        StackLayout checkBoxStack = new StackLayout
                        {
                            HorizontalOptions = LayoutOptions.EndAndExpand
                        };
                        SfCheckBox checkBox = new SfCheckBox();
                        checkBox.SetBinding(SfCheckBox.IsCheckedProperty, "IsSelected");                                            
                        checkBox.StateChanged += SfCheckBox_StateChanged;
                        checkBoxStack.Children.Add(checkBox);
                        headerStack.Children.Add(labelStack);
                        headerStack.Children.Add(checkBoxStack);
                        return new ViewCell { View = headerStack, StyleId = "NewViewCell" };
                    });

                    //groupedListView.DataSource.GroupDescriptors.Add(new Syncfusion.DataSource.GroupDescriptor()
                    //{
                    //    PropertyName = "Category",
                    //    KeySelector = (object obj1) =>
                    //    {
                    //        var item = (obj1 as GroupCheckListItem);
                    //        return item.Category[0].ToString();
                    //    }
                    //});
                }
                fleet_confirm_icon.IsVisible = true;
            }
        }
        catch (Exception e)
        {
            await DisplayAlert("Error", e.Message, "OK");
        }

    }

    async void CheckBox_StateChanged(System.Object sender, Syncfusion.XForms.Buttons.StateChangedEventArgs e)
    {            
        
    }

    public async void fleet_toNextPage(object sender, EventArgs e)
    {
        checkItems.Clear();
        try
        {
            //if (fleet_selectAll.IsChecked == true)
            //{
            //    checkItems.Clear();
            //}

            //else
            //{
            ObservableCollection<GroupedCheckListItem> checkedItems = new ObservableCollection<GroupedCheckListItem>();

            checkedItems = GroupedCheckListModel.CheckedList;
            foreach (GroupedCheckListItem item1 in checkedItems)
            {
                if (item1.IsSelected == false)
                {
                    //checkItems.Add(new clsCheckListItem(item1.Category, item1.Name));
                }
            }
            //}

            var content = await DependencyService.Get<CommonFunctionInterface>().CallWebService(0, null, Ultis.Settings.SessionBaseURI, ControllerUtil.getDownloadMenuURL(), this);
            clsResponse response = JsonConvert.DeserializeObject<clsResponse>(content);

            if (response.IsGood == true)
            {
                var menu = JObject.Parse(content)["Result"].ToObject<clsLogin>();
                //await Navigation.PushAsync(new CheckList2(checkItems, menu.CheckListLinkId));
            }
        }
        catch (Exception exception)
        {
            await DisplayAlert("Error", exception.Message, "Ok");
        }
    }

    async void SfCheckBox_StateChanged(System.Object sender, Syncfusion.XForms.Buttons.StateChangedEventArgs e)
    {
        try
        {
            SfCheckBox checkBox = sender as SfCheckBox;
            var binding = checkBox.BindingContext as Syncfusion.DataSource.Extensions.GroupResult;
            var groupedList = checkItems.GroupBy(x => x.Category);
            foreach (var group in groupedList)
            {
                if (group.Key == binding.Key.ToString())
                {
                    ObservableCollection<GroupedCheckListItem> oriItems = new ObservableCollection<GroupedCheckListItem>();
                    oriItems = GroupedCheckListModel.CheckedList;
                    foreach (var item in oriItems)
                    {
                        if (item.Category == group.Key)
                        {
                            item.IsSelected = checkBox.IsChecked.Value ? true : false;
                        }
                    }
                    break;
                }
            }
        }
        catch (Exception ex)
        {
            await DisplayAlert("Error", ex.Message, "Ok");
        }
    }
}
}

分组检查表模型.cs

using ASolute.Mobile.Models;
using ASolute_Mobile.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
using Xamarin.Forms;

namespace ASolute_Mobile.Models.GroupedCheckListModel
{
    public class GroupedCheckListModel : PropertyChange
    {
        public static ObservableCollection<GroupedCheckListItem> chkList;

    public ObservableCollection<GroupedCheckListItem> Check
    {
        set { SetProperty(ref chkList, value); }
        get { return chkList; }
    }

    public GroupedCheckListModel(List<clsCheckListItem> listItems)
    {
        Check = new ObservableCollection<GroupedCheckListItem>();

        foreach (clsCheckListItem item in listItems)
        {

            Check.Add(AddNew(item.Category, item.Key, item.Value, false));
        };

    }

    public static ObservableCollection<GroupedCheckListItem> CheckedList
    {
        get { return chkList; }
    }

    private GroupedCheckListItem AddNew(string category, string key, string value, bool isSelected)
    {
        var chkItem = new GroupedCheckListItem(category, key, value, isSelected);

        return chkItem;
    }
}







public class GroupingSelectionConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return value;

        return value;
        //GroupResult groupResult = value as GroupResult;
        //SfListView listview = parameter as SfListView;

        //var items = new List<MusicInfo>(groupResult.Items.ToList<MusicInfo>());

        //if ((items.All(listitem => listitem.IsSelected == false)))
        //{
        //    for (int i = 0; i < items.Count(); i++)
        //    {
        //        var item = items[i];
        //        (item as MusicInfo).IsSelected = false;
        //        listview.SelectedItems.Remove(item);
        //    }
        //    return ImageSource.FromResource("CustomSelection.Images.NotSelected.png");
        //}

        //else if ((items.All(listitem => listitem.IsSelected == true)))
        //{
        //    for (int i = 0; i < items.Count(); i++)
        //    {
        //        var item = items[i];
        //        (item as MusicInfo).IsSelected = true;
        //        listview.SelectedItems.Add(item);
        //    }

        //    return ImageSource.FromResource("CustomSelection.Images.Selected.png");
        //}

        //else
        //    return ImageSource.FromResource("CustomSelection.Images.Intermediate.png");

    }

  
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

  
}


public class SelectionBoolToImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        //if ((bool)value)
        //    return ImageSource.FromResource("CustomSelection.Images.Selected.png");
        //else
        //    return ImageSource.FromResource("CustomSelection.Images.NotSelected.png");

        if (value == null)
            return value;

        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
}

分组检查列表项

using System;
namespace ASolute_Mobile.Models.GroupedCheckListModel
{
    public class GroupedCheckListItem : PropertyChange
    {
        private string category;
        private string name;
        private string key;
        private bool isSelected;

    public string Category
    {
        set { SetProperty(ref category, value); }
        get { return category; }
    }

    public string Name
    {
        set { SetProperty(ref name, value); }
        get { return name; }
    }

    public string Key
    {
        set { SetProperty(ref key, value); }
        get { return key; }
    }

    public bool IsSelected
    {
        set { SetProperty(ref isSelected, value); }
        get { return isSelected; }
    }

    public GroupedCheckListItem(string category, string key, string name, bool isSelected)
    {
        Category = category;
        Key = key;
        Name = name;
        IsSelected = isSelected;
    }
}
}
o2rvlv0m

o2rvlv0m1#

SfListView允许像选择复选框一样选择每个组与组中得项.每当使用转换器选择与取消选择项时,GroupHeader模板中得复选框状态都会更新.
在XAML中:

<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
    <syncfusion:SfListView>
        <syncfusion:SfListView.GroupHeaderTemplate>
            <DataTemplate>
                <ViewCell>
                    <ViewCell.View>
                        <Grid BackgroundColor="#d3d3d3">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="30" />
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Label Text="{Binding Key}" Grid.Column="1" VerticalTextAlignment="Center"/>
                            <Image Grid.Column="2" IsVisible="{Binding SelectionMode, Source={x:Reference listView}}" HorizontalOptions="Center" VerticalOptions="Center" Source="{Binding ., Converter={StaticResource GroupingSelectionConverter}, ConverterParameter={x:Reference listView}}">
                                <Image.GestureRecognizers>
                                    <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
                                </Image.GestureRecognizers>
                            </Image>
                        </Grid>
                    </ViewCell.View>
                </ViewCell>
            </DataTemplate>
        </syncfusion:SfListView.GroupHeaderTemplate>
    </syncfusion:SfListView>
</ContentPage>

在转换器中:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
 if (value == null)
return value;

GroupResult groupResult = value as GroupResult;
SfListView list = parameter as SfListView;

var items = new List<MusicInfo>(groupResult.Items.ToList<MusicInfo>());

 if ((items.All(item => item.IsSelected == false)))
 {
for (int i = 0; i < items.Count(); i++)
{
    var item = items[i];
    (item as MusicInfo).IsSelected = false;
    list.SelectedItems.Remove(item);
}
return ImageSource.FromResource("CustomSelection.Images.NotSelected.png");
}

else if ((items.All(item => item.IsSelected == true)))
{
for (int i = 0; i < items.Count(); i++)
{
    var item = items[i];
    (item as MusicInfo).IsSelected = true;
    list.SelectedItems.Add(item);
}
return ImageSource.FromResource("CustomSelection.Images.Selected.png");
}

else
return ImageSource.FromResource("CustomSelection.Images.Intermediate.png");
}

在xaml.cs页中,

using Syncfusion.ListView.XForms.Control.Helpers;
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
var image = (sender as Image);
var groupResult = image.BindingContext as GroupResult;

if (groupResult == null)
    return;
var items = groupResult.Items.ToList<MusicInfo>().ToList();

if ((items.All(listItem => listItem.IsSelected == true)))
{
   for (int i = 0; i < items.Count(); i++)
    {
        var item = items[i];
        (item as MusicInfo).IsSelected = false;
    }
}
else if ((items.All(listItem => listItem.IsSelected == false)))
{
    for (int i = 0; i < items.Count(); i++)
    {
        var item = items[i];
        (item as MusicInfo).IsSelected = true;
    }
}
this.RefreshGroupHeader(groupResult);
listView.RefreshView();
}

private void RefreshGroupHeader(GroupResult group)
{
foreach (var item in this.listView.GetVisualContainer().Children)
{
    if (item.BindingContext == group)
    {
        item.BindingContext = null;
        (item as GroupHeaderItem).Content.BindingContext = null;
    }
}
}

相关问题