一、基本使用(数据源在ViewModel中硬编码)
//①在Models文件夹下,新建Employee.cs文件,创建Employee类型 public class Employee { public int Id { get; set; } public string Name { get; set; } public string Department { get; set; } public string Portrait { get; set; } public string Info { get; set; } } //②在ViewModels文件夹下,创建MainPageViewModel.cs //头像图片复制到Resources/Images文件夹下 public partial class MainPageViewModel:ObservableObject { [ObservableProperty] private ObservableCollection<Employee> employees;
public MainPageViewModel() { employees = new ObservableCollection<Employee> { new Employee{ Id=1,Name="zs",Department="行政部",Portrait="zs.png",Info="这是关于张三的介绍" }, new Employee{ Id=2,Name="ls",Department="行政部",Portrait="ls.png",Info="这是关于李四的介绍" }, new Employee{ Id=3,Name="ww",Department="营销部",Portrait="ww.png",Info="这是关于王五的介绍" }, new Employee{ Id=4,Name="zl",Department="营销部",Portrait="zl.png",Info="这是关于赵六的介绍" }, new Employee{ Id=5,Name="qq",Department="营销部",Portrait="qq.png",Info="这是关于钱七的介绍" } }; } } //③MainPage.xaml使用CollectionView <ContentPage ...... xmlns:vm="clr-namespace:MauiApp16.ViewModels"> <!--使用最简易的关联ViewModel方式--> <ContentPage.BindingContext> <vm:MainPageViewModel /> </ContentPage.BindingContext> <!--ItemsSource属性为数据源--> <CollectionView ItemsSource="{Binding Employees}"> <!--ItemTemplate属性定义外观,类型为DataTemplate--> <!--DataTemplate为迭代的每一条数据项定义样式外观,类似于Vue中的v-for或Blazor中的foreach--> <CollectionView.ItemTemplate> <DataTemplate> <Grid ColumnDefinitions="Auto,Auto" RowDefinitions="Auto,Auto,Auto"> <Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" Aspect="AspectFill" HeightRequest="60" Source="{Binding Portrait}" WidthRequest="60" /> <Label Grid.Row="0" Grid.Column="1" FontAttributes="Bold" Text="{Binding Name}" /> <Label Grid.Row="1" Grid.Column="1" Text="{Binding Department}" /> <Label Grid.Row="2" Grid.Column="1" FontAttributes="Italic" Text="{Binding Info}" VerticalOptions="End" /> </Grid> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </ContentPage>
二、外观设置
1、条件样式:迭代数据项时,根据不同条件,显示不同外观,类似于Vue的v-for中if、Blaozor的foreach中if
//①在Controls文件夹下,创建一个Selector类 public class EmployeeDataTemplateSelector : DataTemplateSelector { //实例化EmployeeDataTemplateSelector时,从外部赋值XingZhengBu和YingXiaoBu属性 public DataTemplate XingZhengBu { get; set; } public DataTemplate YingXiaoBu { get; set; } //参数item为CollectionView迭代数据项,此例为Employee类型对象 protected override DataTemplate OnSelectTemplate(object item, BindableObject container) { return ((Employee)item).Department.Contains("行政部")? XingZhengBu: YingXiaoBu; } } //②在MainPage.xaml文件中使用 <ContentPage ...... xmlns:c="clr-namespace:MauiApp16.Controls" xmlns:vm="clr-namespace:MauiApp16.ViewModels"> <ContentPage.BindingContext> <vm:MainPageViewModel /> </ContentPage.BindingContext> <ContentPage.Resources> <!-- 定义两个DataTemplate --> <!-- 本例仅将部门Label设置为不同的颜色 --> <DataTemplate x:Key="YingXiaoBu"> <Grid ColumnDefinitions="Auto,Auto" RowDefinitions="Auto,Auto,Auto"> ...... <Label Grid.Row="1" Grid.Column="1" Text="{Binding Department}" TextColor="DarkBlue" /> ...... </Grid> </DataTemplate> <DataTemplate x:Key="XingZhengBu"> <Grid ColumnDefinitions="Auto,Auto" RowDefinitions="Auto,Auto,Auto"> ...... <Label Grid.Row="1" Grid.Column="1" Text="{Binding Department}" TextColor="DarkRed" /> ...... </Grid> </DataTemplate>
<!-- 将定义的两个DataTemplate传入DataTemplateSelector --> <!-- 在DataTemplateSelector中,根据迭代的Item数据项条件,使用不同的DataTemplate --> <c:EmployeeDataTemplateSelector x:Key="EmployeeSelector" XingZhengBu="{StaticResource XingZhengBu}" YingXiaoBu="{StaticResource YingXiaoBu}" /> </ContentPage.Resources> <!-- ItemTemplate使用DataTemplateSelector,将迭代数据项作为参数传入到Selector中 --> <CollectionView ItemTemplate="{StaticResource EmployeeSelector}" ItemsSource="{Binding Employees}" /> </ContentPage>
2、排列方式:通过ItemsLayout设置垂直列表、水平列表、垂直网格、水平网格
1)垂直列表(如果不设置ItemsLayout,默认为垂直列表)
<!--简单设置ItemsLayout属性--> <CollectionView ItemsSource="{Binding Employees}" ItemsLayout="VerticalList"> ... </CollectionView> <!--通过元素属性设置ItemsLayout--> <!--垂直/水平列表的类型为LinearItemsLayout--> <CollectionView ItemsSource="{Binding Employees}"> <CollectionView.ItemsLayout> <LinearItemsLayout Orientation="Vertical" /> </CollectionView.ItemsLayout> ... </CollectionView>
2)水平列表
<!--简单设置ItemsLayout属性--> <CollectionView ItemsSource="{Binding Employees}" ItemsLayout="HorizontalList"> ... </CollectionView> <!--通过元素属性设置ItemsLayout--> <!--垂直/水平列表的类型为LinearItemsLayout--> <CollectionView ItemsSource="{Binding Employees}"> <CollectionView.ItemsLayout> <LinearItemsLayout Orientation="Horizontal" /> </CollectionView.ItemsLayout> ... </CollectionView>
3)垂直网格
<!--通过ItemsLayout属性直接设置两列垂直网格--> <CollectionView ItemsSource="{Binding Employees}" ItemsLayout="VerticalGrid, 2"> ...... </CollectionView> <!--通过元素属性,设置两列垂直网格。网格的对象类型为GridItemsLayout--> <CollectionView ItemsSource="{Binding Employees}"> <CollectionView.ItemsLayout> <GridItemsLayout Orientation="Vertical" Span="2" /> </CollectionView.ItemsLayout> ... </CollectionView>
4)水平网格
<!--通过ItemsLayout属性直接设置两列水平网格--> <CollectionView ItemsSource="{Binding Employees}" ItemsLayout="HorizontalGrid, 2"> ...... </CollectionView> <!--通过元素属性,设置两列水平网格。网格的对象类型为GridItemsLayout--> <CollectionView ItemsSource="{Binding Employees}"> <CollectionView.ItemsLayout> <GridItemsLayout Orientation="Horizontal" Span="2" /> </CollectionView.ItemsLayout> ... </CollectionView>
3、页眉页脚Header/Footer设置
1)页眉页脚设置为字符串
<!--设置Header属性和Footer属性--> <CollectionView ItemsSource="{Binding Employees}" Header="Employees" Footer="2023"> ... </CollectionView>
2)页眉页脚中显示视图
<CollectionView ItemsSource="{Binding Employees}"> <CollectionView.Header> <StackLayout BackgroundColor="Gray"> <Label Margin="5" FontAttributes="Bold" FontSize="12" Text="Employees" /> </StackLayout> </CollectionView.Header> <CollectionView.Footer> <StackLayout BackgroundColor="AliceBlue"> <Label Margin="5" FontAttributes="Italic" FontSize="10" Text="2023" /> </StackLayout> </CollectionView.Footer> ...... </CollectionView>
3)页眉页脚设置DataTemplate。使用了DataTemplate后,可以设置条件模板,可自行测试。
<CollectionView Footer="{Binding .}" Header="{Binding .}" ItemsSource="{Binding Employees}"> <CollectionView.HeaderTemplate> <DataTemplate> <StackLayout BackgroundColor="Gray"> <Label Margin="5" FontAttributes="Bold" FontSize="12" Text="Employees" /> </StackLayout> </DataTemplate> </CollectionView.HeaderTemplate> <CollectionView.FooterTemplate> <DataTemplate> <StackLayout BackgroundColor="AliceBlue"> <Label Margin="5" FontAttributes="Italic" FontSize="10" Text="2023" /> </StackLayout> </DataTemplate> </CollectionView.FooterTemplate> ...... </CollectionView>
4、数据项的间距。此时,ItemsLayout需要使用属性元素的方式进行设置(见第2项设置)
1)垂直/水平列表的数据项间距
<CollectionView ItemsSource="{Binding Employees}"> <CollectionView.ItemsLayout> <LinearItemsLayout ItemSpacing="10" Orientation="Vertical" /> </CollectionView.ItemsLayout> ...... </CollectionView>
2)垂直/水平网格的Item数据项间距
<CollectionView ItemsSource="{Binding Employees}"> <CollectionView.ItemsLayout> <GridItemsLayout Orientation="Vertical" Span="2" VerticalItemSpacing="20" HorizontalItemSpacing="30" /> </CollectionView.ItemsLayout> ... </CollectionView>
5、数据项大小调整的策略
<!--默认值MeasureAllItems,每一项都进行大小调整--> <CollectionView ... ItemSizingStrategy="MeasureAllItems"> ... </CollectionView> <!--MeasureFirstItem值,后续数据项都根据第一项大小为准-> <CollectionView ... ItemSizingStrategy="MeasureFirstItem"> ... </CollectionView>
6、数据项对齐方式
<!--默认为左对齐,通过在ContentPage上设置FlowDirection属性,修改为右对齐--> <ContentPage ...... FlowDirection="RightToLeft"> <StackLayout Margin="20"> <CollectionView ItemsSource="{Binding Monkeys}"> ... </CollectionView> </StackLayout> </ContentPage>
7、动态调整数据项的大小
//XAML文件中,ImageButton定义Clicked事件 <ContentPage ......><Grid RowDefinitions="*,50"><CollectionView ...... <CollectionView.ItemTemplate> <DataTemplate> <Grid ...> <ImageButton Clicked="ImageButton_Clicked" HeightRequest="60" WidthRequest="60" Source="{Binding Portrait}"/> ...... </Grid> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </Grid> </ContentPage> //后台代码Clicked事件中,更改ImageButton的尺寸 private void ImageButton_Clicked(object sender, EventArgs e) { var imageButton = sender as ImageButton; imageButton.HeightRequest = imageButton.WidthRequest = imageButton.HeightRequest.Equals(60) ? 100 : 60; }
8、轻扫上下文菜单,结合SwipeView控件
<ContentPage ......> <ContentPage.BindingContext> <vm:MainPageViewModel /> </ContentPage.BindingContext> <CollectionView ......> </CollectionView.ItemsLayout> <CollectionView.ItemTemplate> <DataTemplate> <!--使用SwipeView控件,包装DataTemplate对象--> <SwipeView> <!--设置左滑菜单,还可以设置右滑、上滑、下滑--> <SwipeView.LeftItems> <!--设置两个菜单,收藏和删除--> <!--点击菜单,响应相应的命令,参数为当前行。设置为{Binding}或{Binding .}均可--> <SwipeItems> <SwipeItem BackgroundColor="AliceBlue" Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.FavoriteCommand}" CommandParameter="{Binding}" Text="收藏" /> <SwipeItem BackgroundColor="LightGray" Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.DeleteCommand}" CommandParameter="{Binding .}" Text="删除" /> </SwipeItems> </SwipeView.LeftItems> <Grid> ...... </Grid> </SwipeView> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </ContentPage> //ViewModel中的命令(DeleteCommand) [RelayCommand] private void Delete(Employee employee) { employees.Remove(employee); }
三、数据源设置
1、数据项选择控制
1)单选及设置预选
<ContentPage ......> <ContentPage.BindingContext> <vm:MainPageViewModel /> </ContentPage.BindingContext> <VerticalStackLayout> <!-- SelectionMode设置选择模式,Single-单选、Multiple-多选,None-禁用选择 SelectedItem设置初始预选项目,通过ViewModel设置。在后台代码中,将SelectedItem设置为null,则可以清除选择! 单选时,SelectedItem为双向绑定,Label的Text显示选定项目 SelectionChanged选择更改时触发的事件 --> <Label Text="{Binding SelectedEmployee.Name}" /> <CollectionView ItemsSource="{Binding Employees}" SelectedItem="{Binding SelectedEmployee}" SelectionChanged="CollectionView_SelectionChanged" SelectionMode="Single"> <CollectionView.ItemTemplate> ...... </CollectionView.ItemTemplate> </CollectionView> </VerticalStackLayout> </ContentPage> //ViewModel设置初始预先项目SelectedEmployee public partial class MainPageViewModel:ObservableObject { [ObservableProperty] private ObservableCollection<Employee> employees; [ObservableProperty] private Employee selectedEmployee; public MainPageViewModel() { employees = new ObservableCollection<Employee> { new Employee{ Id=1,Name="zs",Department="行政部",Portrait="zs.png",Info="这是关于张三的介绍" }, new Employee{ Id=2,Name="ls",Department="行政部",Portrait="ls.png",Info="这是关于李四的介绍" }, new Employee{ Id=3,Name="ww",Department="营销部",Portrait="ww.png",Info="这是关于王五的介绍" }, new Employee{ Id=4,Name="zl",Department="营销部",Portrait="zl.png",Info="这是关于赵六的介绍" }, new Employee{ Id=5,Name="qq",Department="营销部",Portrait="qq.png",Info="这是关于钱七的介绍" } }; selectedEmployee = employees.Skip(2).FirstOrDefault(); } }
2)多选及设置预选
<ContentPage ......> <ContentPage.BindingContext> <vm:MainPageViewModel /> </ContentPage.BindingContext> <VerticalStackLayout> <!-- SelectionMode设置选择模式,Single-单选、Multiple-多选 SelectedItems设置初始预选项目,通过ViewModel设置。多选时,SelectedItems为单向绑定 --> <CollectionView ItemsSource="{Binding Employees}" SelectedItems="{Binding SelectedEmployees}" SelectionMode="Multiple"> <CollectionView.ItemTemplate> ...... </CollectionView.ItemTemplate> </CollectionView> </VerticalStackLayout> </ContentPage> //ViewModel中设置SelectedEmployees public partial class MainPageViewModel:ObservableObject { ...... [ObservableProperty] private ObservableCollection<Employee> selectedEmployees; public MainPageViewModel() { ...... selectedEmployees = new ObservableCollection<Employee> { employees[0], employees[3] }; } }
3)设置选择颜色
<!--设置待定颜色稍显复杂,需要通过可视状态来设置--> <!--Style的TargetType需设置为DataTemplate的根元素,本例中为Grid--> <ContentPage ...> <ContentPage.Resources> <Style TargetType="Grid"> <Setter Property="VisualStateManager.VisualStateGroups"> <VisualStateGroupList> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal" /> <VisualState x:Name="Selected"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="LightSkyBlue" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateGroupList> </Setter> </Style> </ContentPage.Resources> <StackLayout Margin="20"> <CollectionView ItemsSource="{Binding Monkeys}" SelectionMode="Single"> ..... </CollectionView> </StackLayout> </ContentPage>
2、EmptyView:设置数据源不可用时,显示的替代内容
1)数据不可用时,显示字符串
<!--数据源EmptyEmployees为null,显示EmptyView的字符串值--> <CollectionView ItemsSource="{Binding EmptyEmployees}" EmptyView="无数据显示"> ...... </CollectionView>
2)数据不可用时,显示视图(ContentView)
<CollectionView ItemsSource="{Binding EmptyEmployees}"> <CollectionView.EmptyView> <!--ContentView可以省略--> <ContentView> <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"> <Label Margin="10,25,10,10" FontAttributes="Bold" FontSize="18" HorizontalOptions="Fill" HorizontalTextAlignment="Center" Text="无数据显示" /> </StackLayout> </ContentView> </CollectionView.EmptyView> ...... </CollectionView>
3)运行时再确定数据不可用时显示的视图方式一:ContentView
<ContentPage ......> <!--定义两个ContentView资源--> <ContentPage.Resources> <ContentView x:Key="EmptyViewA"> <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"> <Label FontSize="18" Text="无数据显示A" /> </StackLayout> </ContentView> <ContentView x:Key="EmptyViewB"> <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"> <Label FontSize="18" Text="无数据显示B" /> </StackLayout> </ContentView> </ContentPage.Resources> <VerticalStackLayout> <!--通过Swith的Toggled事件,后台代码更改CollectionView的EmptyView属性--> <Switch Toggled="Switch_Toggled"/> <CollectionView x:Name="collectionView" ItemsSource="{Binding EmptyEmployees}"> <CollectionView.ItemTemplate> ...... </CollectionView.ItemTemplate> </CollectionView> </VerticalStackLayout> </ContentPage> //Switch的Toggled事件上 private void Switch_Toggled(object sender, ToggledEventArgs e) { collectionView.EmptyView = e.Value ? Resources["EmptyViewA"] : Resources["EmptyViewB"]; }
4、下拉刷新?
5、增量加载?
四、列表滚动控制
1、滚动事件
<CollectionView Scrolled="CollectionView_Scrolled"> ...... </CollectionView> //ItemsViewScrolledEventArgs类型参数定义了丰富的属性,包括: //HorizontalDelta/VerticalDelta:水平/垂直滚动量 //HorizontalOffset/VerticalOffset:相对于原点的水平/垂直偏移量 //FirstVisibleItemIndex/LastVisibleItemIndex/CenterItemIndex:列表中可见的第一项/最后一项/中间项索引 private async void CollectionView_Scrolled(object sender, ItemsViewScrolledEventArgs e) { ...... }
2、代码控件滚动
1)滚动到索引
//滚动到索引为5的数据项,并将数据项显示在列表可视窗的开始位置 collectionView.ScrollTo(5,position:ScrollToPosition.Start); //分组数据时,滚动到第2组,索引为1的数据项 collectionView.ScrollTo(2, 1);
2)滚动到Item数据项
//获取当前页面的BindingContext,并转化为页面对应的ViewModel对象 var viewModel = BindingContext as MainPageViewModel; //筛选ViewModel中的Employees数据集合,并选取Name为qq的第一条数据 var person = viewModel.Employees.FirstOrDefault(e=>e.Name=="qq"); //滚动到这条数据项,在列表窗口的开始位置显示,并禁用滚动动画 collectionView.ScrollTo(person,position:ScrollToPosition.Start,animate:false); //分组数据滚动 GroupedAnimalsViewModel viewModel = BindingContext as GroupedAnimalsViewModel; AnimalGroup group = viewModel.Animals.FirstOrDefault(a => a.Name == "Monkeys"); Animal monkey = group.FirstOrDefault(m => m.Name == "Proboscis Monkey"); collectionView.ScrollTo(monkey, group);
五、数据分组显示 :
总体分为两步:一、设置分组数据源;二、在XAML中显示分组;三、设置页眉、页脚、空组显示等,可详见文档。
标签:数据项,控件,Name,CollectionView,......,6.4,Employee,new,public From: https://www.cnblogs.com/functionMC/p/17020024.html