我正在尝试实现一个CollectionView,如下图所示。正如你所看到的,如果一个元素被选中,它在右上角有一个对应的复选标记
首先,我试图在SelectionChanged事件中找到AbstractLayout类别ID,并且已经在其中查找了名为=“showIfSelected”的元素,但是在collectionView中搜索时,我总是得到null。我已经阅读了几篇关于为什么会出现这种情况的文章,但是我还没有找到解决问题的方法。也许有人可以告诉我最终如何达到我需要的结果?
.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodels="clr-namespace:Paraglider.MobileApp.ViewModels"
xmlns:models="clr-namespace:Paraglider.MobileApp.Models"
x:DataType="viewmodels:CatalogPageViewModel"
x:Class="Paraglider.MobileApp.Pages.CatalogPage">
<Grid BackgroundColor="#FFFEF6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="10*" />
</Grid.RowDefinitions>
...
<ScrollView Grid.Row="1" Grid.ColumnSpan="2" Margin="20, 0" VerticalScrollBarVisibility="Never">
<CollectionView
x:Name="collectionView"
Grid.Row="2" Grid.ColumnSpan="2"
ItemsSource="{Binding Categories}"
SelectionMode="Multiple"
SelectionChanged="CollectionView_SelectionChanged">
<CollectionView.Header>...</CollectionView.Header>
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="{OnIdiom Default=2}" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:Category">
<AbsoluteLayout x:Name="{Binding Id}">
<Image
Aspect="AspectFit"
WidthRequest="165"
Source="pzv.svg"
Margin="0, 10" />
<Image
x:Name="showIfSelected"
Aspect="AspectFit"
AbsoluteLayout.LayoutBounds="130, 0, autoSize, autoSize"
Source="selected_category.svg"
IsVisible="True" >
<Image.Shadow>
<Shadow Brush="Black" Offset="0, 10" Opacity="0.1" Radius="15" />
</Image.Shadow>
</Image>
</AbsoluteLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ScrollView>
</Grid>
</ContentPage>
.xaml.cs:
public partial class CatalogPage : ContentPage
{
public CatalogPage(CatalogPageViewModel viewModel)
{
InitializeComponent();
BindingContext = viewModel;
}
private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var prev = e.PreviousSelection.Select(x => (Category)x).ToList();
var current = e.CurrentSelection.Select(x => (Category)x).ToList();
var unselected = prev.ExceptBy(current.Select(x => x.Id), x => x.Id).ToList();
foreach (var item in unselected)
{
var layout = this.FindByName<AbsoluteLayout>($"{item.Id}");
var image = layout.FindByName<Image>("showIfSelected");
image.IsVisible = false;
}
var selected = current.ExceptBy(prev.Select(x => x.Id), x => x.Id).ToList();
foreach (var item in selected)
{
var layout = this.FindByName<AbsoluteLayout>($"{item.Id}");
var image = layout.FindByName<Image>("showIfSelected");
image.IsVisible = true;
}
}
}
2条答案
按热度按时间xoefb8l81#
合并样式:https://learn.microsoft.com/en-us/dotnet/maui/user-interface/styles/xaml?view=net-maui-7.0
和视觉状态:https://learn.microsoft.com/en-us/dotnet/maui/user-interface/visual-states?view=net-maui-7.0
您可以使用VisualState来确定要使用的样式。CollectionView具有一个选定的VisualState。
您可以命名您的可视元素,比方说图片,并使用样式来更改该可视元素的属性。
不需要这堵文本墙,一切都可以在XAML中完成,不需要任何代码。
编辑:其他用户建议,你可能需要例子如何做到这一点。这是一个工作代码,从我的一个测试项目(在MAUI NET 7.0)
您可以注意到的重要部分是,我有一个Label VisualElement,它的名称为“line1”,我访问属性TextColor,并在选中项目时应用值Black。
如果应用此样式,并且未能提供Label类型的子VisualElement和指定的Name,则会引发严重的运行时异常。
从好的方面来说,这种方法的替代方案更耗时(在量级上),也容易出错。
希望这能帮上忙。
bqjvbblv2#
正如Jason所建议的,您可以直接将
IsVisible
绑定到您的Model的属性,如下所示: