Xamarin Select 全部在 ListView 中

Xamarin Select All in ListView

我希望有一个 Select All 复选框,它会在选中或取消选中时更新列表视图中的所有其他复选框,但我找不到更新它们的方法。我已经尝试了一个 foreach 语句,以及 ViewModel 中的一个 for 语句和 运行 当 Select All 复选框被更改时的任务,但它们似乎没有更新 UI.感谢任何帮助!

查看模型:

 public class SyncViewModel : BaseViewModel
    {
        public ObservableCollection<Company> CompaniesCollection { get; set; }
        public ObservableCollection<WellGroup> WellGroupCollection { get; set; }
        public ObservableCollection<Well> WellsCollection { get; set; }

        public SyncViewModel()
        {
            Title = "Sync";
            CompaniesCollection = new ObservableCollection<Company>();
            WellGroupCollection = new ObservableCollection<WellGroup>();
            WellsCollection = new ObservableCollection<Well>();
        }

        public async Task InitializeData()
        {

            var wellDataStore = new WellDataStore();

            var companies = await wellDataStore.GetAllGroups();
            if (companies != null)
            {
                CompaniesCollection.Clear();

                foreach (var company in companies)
                {
                    CompaniesCollection.Add(company);
                }
            }

        }
        
        public async Task SyncData()
        {

            IsBusy = true;

            // load and process data
            IsBusy = false;
            
        } 
    }
}

xaml:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:viewModel="clr-namespace:SiteVisits.ViewModels" xmlns:model="clr-namespace:SiteVisits.Models" 
             x:DataType="viewModel:SyncViewModel"
             x:Class="SiteVisits.Views.Sync">

    <ContentPage.ToolbarItems>
        <ToolbarItem Text="Sync" Clicked="Sync_Clicked" />
    </ContentPage.ToolbarItems>
    <StackLayout>
        <ActivityIndicator 
            IsVisible="{Binding IsBusy}" 
            IsRunning="{Binding IsBusy}" />
        <CheckBox x:Name="SelectAll" Color="Blue" CheckedChanged="CheckAll"  />
        <Label Text="Select All" FontSize="Large" VerticalOptions="Center"/>
        <ListView x:Name="Companies"
                ItemsSource="{Binding CompaniesCollection}"
                SelectionMode="Single"
                HasUnevenRows="True"
                ItemTapped="Companies_Selection">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Padding="10" x:DataType="model:Company">
                            <CheckBox x:Name="Name" Color="Blue" IsChecked="{Binding IsChecked}" />
                            <Label Text="{Binding Name}" 
                                        FontSize="Large"
                                        VerticalOptions="Center"/>
                        </StackLayout>

                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

xaml.cs:

  SyncViewModel viewModel;
        public Sync(SyncViewModel viewModel)
        {
            InitializeComponent();

            this.viewModel = viewModel;
            BindingContext = this.viewModel;
        }
       
        protected override async void OnAppearing()
        {
            await viewModel.InitializeData();
        }

        async private void Sync_Clicked(object sender, EventArgs e)
        {
            await viewModel.SyncData(); 
        }

        private void Companies_Selection(object sender, ItemTappedEventArgs e)
        {

            if (e.Item != null)
            {
                var company = e.Item as Company;
                company.IsChecked = !company.IsChecked;
            }
        }

由于您使用的是 MVVM,我会为复选框使用绑定

    <CheckBox x:Name="SelectAll" Color="Blue" IsChecked="{Binding AllChecked}"  />

那么你将需要这个 bool 属性,像这样。所以当值改变时,它会更新所有集合

    private bool _allChecked;
    public bool AllChecked { get => _allChecked;
        set
        {
            if (value != _allChecked)
            {
                UpdateCompaniesCollection(value);
                OnPropertyChanged(nameof(AllChecked));
            }
        }
    }

然后您将需要更新集合的方法。一种方法是

    void UpdateCompaniesCollection(bool newValue)
    {
        for(int i = 0; i < CompaniesCollection.Count; i++)
        {
            var tempCompany = CompaniesCollection[i];
            tempCompany.IsChecked = newValue;
            CompaniesCollection[i] = tempCompany;
        }
    }

这应该可以解决问题。这只会在选中复选框时触发集合内元素的更改。但如果你还想反过来(如果一个项目未选中,则取消选中 allCheck),那就更复杂了。