CollectionView SelectionChange事件在Android中无法正常工作(.NET MAUI)

发布于 2025-02-12 07:09:29 字数 7307 浏览 1 评论 0原文

我正在尝试在.NET MAUI中创建自定义标签控件,为此,我首先尝试使用ScrollView和BindableStackLayout控件尝试过它,但是在此,我面临问题。

这里报告 solollview bug

,作为另一种方法或工作,我试图使用CollectionView开发相同的选项卡控制。

这种替代方法在iOS中工作正常,但在Android中无法正常工作。

在Android和iOS中都有一个问题。我将BoxView Control作为所选选项卡的指示器。我将仅显示选定的选项卡,但这仅在第一个选项卡中显示,当我单击其他选项卡时,该选项卡会更改,但不会从第一个选项卡中隐藏并在其他选定的选项卡中可见。

我已经为选定状态使用了带有白色的Visual State Manager,因为它看起来像是我尝试使用BoxView创建的指示器。但这也显示仅当该视图获得iOS加载时,我必须先选择选项卡,然后仅在其中显示所选颜色。

这是我所做的:

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.forms(Visual Studio 2019)中再次正常工作,这只是在MAUI中不起作用,所以有人注意到类似这样的东西吗?

如何重现错误:检查github

I'm trying to create custom tabs control in .Net MAUI, for that, I had first tried it with ScrollView and BindableStackLayout control but in that, I'm facing a problem.

Reported here Custom tabs with ScrollView bug

So, as an alternative approach or work-around, I have tried to develop the same Tabs control using CollectionView.

This alternative approach is working fine in iOS but not working properly in Android.

There is one problem that is common in both Android and iOS. I have taken BoxView control as an Indicator for the selected tab. That I'm going to show only for the Selected tab but this just shows in the first tab, when I click on other tabs the tabs get changed but it does not get hidden from the first tab and get visible in the other selected tab.

I have used the visual state manager with white color for the selected state because it gives looks like an indicator which I',m trying to create using BoxView. But this also shows Selected item for Android only when that view gets loads for iOS I have to select the tab first then only it shows the selected color there.

Here is what I have done:

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));
        }
    }
}

Note: This same approach again works fine in Xamarin.Forms (Visual Studio 2019), this just not working in MAUI, so does anyone notice something like this?

How to Reproduce error: check github

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

药祭#氼 2025-02-19 07:09:29
  1. 删除项目中的BoxView默认样式。资源&gt;样式&gt; styles.xml

     &lt; style targetType =“ boxView”&gt;
     &lt; setter property =“ color” value =“ {appthemebinding light = {staticResource gray950},dark = {staticResource gray200}}” /&gt;
     
  2. 您可以使用iSVisible属性显示boxview是否而不是用boxColor绑定颜色。删除selectionChangedCommandselectionChangedCommandParameterVisualStateManager.VisalStateGroups in Collection> Collection> Collection view以及。

    >

     &lt; boxview grid.row =“ 1”
                              颜色=“黄色”                                 
                              Isvisible =“ {binding Isselected}”/&gt;
     
  3. 设置selectedtab属性如下。

      public tabViewModel selectedtab
     {
         get =&gt; _selectedTab;
         放
         {
             _selectedTab = value;
             setSelection();
             onProperTychanged(nameof(selectedTab));
         }
     }
    
      私有void setSelection()
     {             
         foreach(选项卡中的var项目)
         {
             item.isselected = false;
         }
         selectedtab.isselected = true;
     }
     

  1. Remove the BoxView default style in your project. Resource> Styles> Styles.xml

    <Style TargetType="BoxView">
     <Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
    
  2. You could use the IsVisible property to show the BoxView or not instead of binding color with BoxColor. Remove the SelectionChangedCommand, SelectionChangedCommandParameter and VisualStateManager.VisualStateGroups in CollectionView as well.

     <BoxView Grid.Row="1"
                              Color="Yellow"                                 
                              IsVisible="{Binding IsSelected}"/>
    
  3. Set the SelectedTab property like below.

    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;
     }
    

enter image description here

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文