【问题标题】:CollectionView SelectionChange event not working properly in Android (.Net MAUI)CollectionView SelectionChange 事件在 Android (.Net MAUI) 中无法正常工作
【发布时间】:2022-07-04 17:18:22
【问题描述】:

我正在尝试在 .Net MAUI 中创建自定义选项卡控件,为此,我首先尝试使用 ScrollView 和 BindableStackLayout 控件,但在这方面,我遇到了问题。

在这里举报Custom tabs with ScrollView bug

因此,作为一种替代方法或解决方法,我尝试使用 CollectionView 开发相同的 Tabs 控件。

这种替代方法在 iOS 中运行良好,但在 Android 中无法正常运行。

有一个问题在 Android 和 iOS 中都很常见。我已将 BoxView 控件用作所选选项卡的指示器。我将只为 Selected 选项卡显示,但这仅显示在第一个选项卡中,当我单击其他选项卡时,选项卡会发生更改,但它不会从第一个选项卡中隐藏并在另一个选定的选项卡中可见。

我已经为所选状态使用了白色的可视状态管理器,因为它看起来像我正在尝试使用 BoxView 创建的指示器。但这也仅在该视图为 iOS 加载时才显示 Android 的 Selected item 我必须先选择选项卡,然后它才会在那里显示选定的颜色。

这是我所做的:

MainPage.xaml

<ContentPage.Content>

    <Grid RowDefinitions="50, *" RowSpacing="0">

        <CollectionView x:Name="TabsView"
                        Grid.Row="0"
                        ItemsSource="{Binding Tabs,Mode=TwoWay}"
                        ItemsUpdatingScrollMode="KeepItemsInView"
                        ItemSizingStrategy="MeasureAllItems"
                        SelectedItem="{Binding SelectedTab}"
                        SelectionChangedCommand="{Binding Path=BindingContext.TabChangedCommand,Source={x:Reference TabsView}}"
                        SelectionChangedCommandParameter="{Binding SelectedTab}"
                        SelectionMode="Single">

            <CollectionView.ItemsLayout>
                <LinearItemsLayout Orientation="Horizontal"/>
            </CollectionView.ItemsLayout>

            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid RowSpacing="0" RowDefinitions="*, 3">
                        
                        <Label Grid.Row="0"
                                    Text="{Binding TabTitle}"
                                    TextColor="White"
                                    BackgroundColor="navy"
                                    Padding="20,0"
                                    VerticalTextAlignment="Center"
                                    HorizontalTextAlignment="Center"
                                    FontSize="12" />
                        <BoxView Grid.Row="1" Color="{Binding BoxColor}"
                                    IsVisible="{Binding IsSelected}"/>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup Name="CommonStates">
                                <VisualState Name="Normal"/>
                                <VisualState Name="Selected">
                                    <VisualState.Setters>
                                        <Setter Property="BackgroundColor" Value="White" />
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Grid>
                </DataTemplate>

            </CollectionView.ItemTemplate>
        </CollectionView>

        
        <tabs:ParentRecordTabView Grid.Row="1"
                                    IsVisible="{Binding IsParentRecordTabVisible}"
                                    VerticalOptions="FillAndExpand"/>

        <tabs:AdditionalInfoTabView Grid.Row="1"
                                    IsVisible="{Binding IsAdditionalInfoTabVisible}"
                                    VerticalOptions="FillAndExpand" />
        


    </Grid>

</ContentPage.Content>

MainPageViewModel.cs

public class MainPageViewModel : BaseViewModel
{
    public MainPageViewModel()
    {
        GetTabs();
    }

    private bool _isParentRecordTabVisible = true;
    private bool _isAdditionalInfoTabVisible;

    private ObservableCollection<TabViewModel> _tabs { get; set; }
    private TabViewModel _selectedTab { get; set; }

    public bool IsParentRecordTabVisible
    {
        get => _isParentRecordTabVisible;
        set { _isParentRecordTabVisible = value; OnPropertyChanged(nameof(IsParentRecordTabVisible)); }
    }

    public bool IsAdditionalInfoTabVisible
    {
        get => _isAdditionalInfoTabVisible;
        set { _isAdditionalInfoTabVisible = value; OnPropertyChanged(nameof(IsAdditionalInfoTabVisible)); }
    }

    public ObservableCollection<TabViewModel> Tabs
    {
        get => _tabs;
        set { _tabs = value; OnPropertyChanged(nameof(Tabs)); }
    }

    public TabViewModel SelectedTab
    {
        get => _selectedTab;
        set
        {
            _selectedTab = value;
            OnPropertyChanged(nameof(SelectedTab));
        }
    }

    public ICommand TabChangedCommand { get { return new Command<TabViewModel>(ChangeTabClick); } }

    private void GetTabs()
    {
        Tabs = new ObservableCollection<TabViewModel>();
        Tabs.Add(new TabViewModel { TabId = 1, IsSelected = true, TabTitle = "Parent record" });
        Tabs.Add(new TabViewModel { TabId = 2, TabTitle = "Additional Info" });
        Tabs.Add(new TabViewModel { TabId = 3, TabTitle = "Contacts" });
        Tabs.Add(new TabViewModel { TabId = 4, TabTitle = "Previous inspections" });
        Tabs.Add(new TabViewModel { TabId = 5, TabTitle = "Attachments" });

        SelectedTab = Tabs.FirstOrDefault();
    }

    public void ChangeTabClick(TabViewModel tab)
    {
        Tabs.All((arg) =>
        {
            if (arg.TabId == tab.TabId)
            {
                arg.IsSelected = true;
            }
            else
            {
                arg.IsSelected = false;
            }
            return true;
        });
        SelectedTab = Tabs.Where(t => t.IsSelected == true).FirstOrDefault();

        switch (SelectedTab.TabId)
        {
            case 1:
                IsParentRecordTabVisible = true;
                IsAdditionalInfoTabVisible = false;
                break;
            case 2:
                IsParentRecordTabVisible = false;
                IsAdditionalInfoTabVisible = true;
                break;
        }
    }
}

TabViewModel.cs

public class TabViewModel : BaseViewModel
{
    private bool _IsSelected;
    public bool IsSelected
    {
        get { return _IsSelected; }
        set
        {
            _IsSelected = value;
            OnPropertyChanged(nameof(IsSelected));
        }
    }

    private int _TabId;
    public int TabId
    {
        get { return _TabId; }
        set
        {
            _TabId = value;
            OnPropertyChanged(nameof(TabId));
        }
    }

    private string _TabTitle;
    public string TabTitle
    {
        get { return _TabTitle; }
        set
        {
            _TabTitle = value;
            OnPropertyChanged(nameof(TabTitle));
        }
    }
}

注意:同样的方法在 Xamarin.Forms (Visual Studio 2019) 中也可以正常工作,只是在 MAUI 中不起作用,所以有人注意到这样的事情吗?

如何重现错误:check github

【问题讨论】:

    标签: xamarin xamarin.android .net-6.0 maui .net-maui


    【解决方案1】:
    1. 删除项目中的 BoxView 默认样式。资源> 样式> Styles.xml

      <Style TargetType="BoxView">
       <Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
      
    2. 您可以使用IsVisible 属性来显示或不显示BoxView,而不是使用BoxColor 绑定颜色。删除CollectionView 中的SelectionChangedCommandSelectionChangedCommandParameterVisualStateManager.VisualStateGroups

       <BoxView Grid.Row="1"
                                Color="Yellow"                                 
                                IsVisible="{Binding IsSelected}"/>
      
    3. 如下设置SelectedTab 属性。

      public TabViewModel SelectedTab
       {
           get => _selectedTab;
           set
           {
               _selectedTab = value;
               SetSelection();
               OnPropertyChanged(nameof(SelectedTab));
           }
       }
      
        private void SetSelection()
       {             
           foreach (var item in Tabs)
           {
               item.IsSelected = false;
           }
           SelectedTab.IsSelected = true;
       }
      

    【讨论】:

      猜你喜欢
      • 2022-06-30
      • 2022-11-04
      • 1970-01-01
      • 2022-12-11
      • 1970-01-01
      • 2018-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多