首页 > 解决方案 > 无法在 CollectionView 中选择一个项目两次,当尝试解决时,在 Xamarin Forms 中触发事件两次

问题描述

我正在使用 MVVM 模式。我有一个CollectionView选择时调用ViewModel中的 Command 的项目。

第一个问题是我不能两次选择一个项目。我可以有一些解决方法,让它像设置一样工作CollectionView.SelectedItem = null

第二个问题是,当我设置时CollectionView.SelectedItem = nullSelectionChangedCommand被调用了两次(第一次是为了选择一个项目,第二次是因为设置SelectedItem = null)。这是Company Selected Name = " + SelectedCompany.Name在 ViewModel 中打印两次。

这是我的 XAML 代码:

<CollectionView ItemsSource="{Binding CompanyListItems}" SelectedItem="{Binding SelectedCompany}"
                             SelectionChangedCommand="{Binding CompanySelectedCommand}"
                             SelectionMode="Single" SelectionChanged="SelectionChanged">
                             SelectionChanged="SelectionChanged">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <StackLayout>
                <Label Text="{Binding Name}" />
            </StackLayout>
        </DataTemplate>
</CollectionView>

C#代码背后:

void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if ((sender as CollectionView).SelectedItem != null)
        (sender as CollectionView).SelectedItem = null;
}

视图模型

public class CompaniesListPageViewModel : INotifyPropertyChanged
{
    public CompaniesListPageViewModel()
    {
        CompanySelectedCommand = new Command<SelectionChangedEventArgs>(execute: (SelectionChangedEventArgs args) => CompanySelected(args));
    }

    public CompanyListItem SelectedCompany
    {
        get { return selectedCompany; }
        set
        {
            if (value != null)
            {
                selectedCompany = value;
                OnPropertyChanged(nameof(SelectedCompany));
            }
        }
    }

    CompanyListItem selectedCompany;

    void CompanySelected(SelectionChangedEventArgs args)
    {
        Debug.WriteLine("Company Selected Name = " + SelectedCompany.Name); 
        Navigation.PushAsync(new CompanyDetailPage(SelectedCompany));
    }
}

标签: c#xamlxamarinxamarin.formsmvvm

解决方案


由于您已SelectionChanged在 Code Behind 中使用过,因此您的 xaml 中不需要SelectionChangedCommand

请参考以下代码,我在示例代码VerticalListSingleSelectionPage.xaml.cs上进行了测试,它在我这边工作正常。

    <CollectionView ItemsSource="{Binding Monkeys}"
                    SelectionMode="Single"                      
                    SelectionChanged="OnCollectionViewSelectionChanged">

和后面的代码:

    void   OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var MyCollectionView = sender as CollectionView;
        if (MyCollectionView.SelectedItem == null)
            return;

         UpdateSelectionData(e.PreviousSelection, e.CurrentSelection);

        //clear selection 
        MyCollectionView.SelectedItem = null;
    }

    void UpdateSelectionData(IEnumerable<object> previousSelectedItems, IEnumerable<object> currentSelectedItems)
    {
        string previous = (previousSelectedItems.FirstOrDefault() as Monkey)?.Name;
        string current = (currentSelectedItems.FirstOrDefault() as Monkey)?.Name;

        Monkey currentMonkey  = (currentSelectedItems.FirstOrDefault() as Monkey);

        if (currentMonkey!=null) { 
           Navigation.PushAsync(new DetailPage(currentMonkey));
        }
    }

更新:

我想用 MVVM 来做。因此,我想从我的 ViewModel 类导航到另一个页面。

为此,您可以参考以下代码:

async void  MonkeySelectionChangedAsync()
{
    if (SelectedMonkey!=null) {
        SelectedMonkeyMessage = $"Selection {selectionCount}: {SelectedMonkey.Name}";
        OnPropertyChanged("SelectedMonkeyMessage");
        selectionCount++;

        System.Diagnostics.Debug.WriteLine("-----------> " + SelectedMonkey.Name);

        await Application.Current.MainPage.Navigation.PushAsync(new DetailPage(SelectedMonkey));
    }
}

你首先需要selectedMonkey null你的视图模型的构造函数中初始化。

    public MonkeysViewModel()
    {
        selectedMonkey = null;

        //  other code

     }

之后,分配SelectedItemnull函数OnAppearing

       protected override void OnAppearing()
    {
        base.OnAppearing();
        //mCollectionView is the `x:Name` of your `CollectionView`
        mCollectionView.SelectedItem = null;   
    }

而xaml是:

    <CollectionView 
                    x:Name="mCollectionView"
                    ItemsSource="{Binding Monkeys}"
                    SelectionMode="Single"           
                    SelectedItem="{Binding SelectedMonkey}"
                    SelectionChangedCommand="{Binding MonkeySelectionChangedCommand}"
                   >

注意:您可以根据上面的代码修改您的代码。


推荐阅读