我对 xaml 和 .net maui 还很陌生,但我真的不知道该使用哪些搜索词。我想用集合视图在 xaml 中列出今天的任务通知。我希望此列表在 xaml 集合视图中显示时,使用 TaskID 作为标识符键从另一个列表中提取详细信息。
例如,大致:
class Notification:
int Id;
int TaskID;
int Title;
DateTime NotificationTime;
class Task:
int Id;
string Name;
string Details;
UpcomingNotificationsViewModel:
List<Notification> NotificationsList { get; set; }
List<Task> TasksList { get; set; }
async void LoadData()
{
var result = from s in NotificationsList
where s.NotificationTime.Date == today
group s by s.NotificationTime into g
select new GroupedNotification{ NotificationTime = g.Key, Notification = g.ToList() };
GroupedNotifications = result;
}
public class GroupedNotification
{
public DateTime NotifyTime { get; set; }
public List<Notification> Notification { get; set; }
}
在 XAML 中,在迭代通知的 CollectionView 时,我还想从 TasksList 中提取数据,例如 Task.Name、Task.Details 等。
<CollectionView ItemsSource="{Binding GroupedNotifications}">
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout>
<!-- Display the group header (time) -->
<Label Text="{Binding NotifyTime, StringFormat='{}{0:h\\:mm tt}'}"
FontAttributes="Bold"
TextColor="Blue"/>
<!-- Display the notifications within the group -->
<CollectionView ItemsSource="{Binding Notification}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="0,5">
<Frame Padding="10,10">
<StackLayout>
<Label Text="{Binding Title}" />
<Label Text="{Binding NotificationTime}" />
//this label below, how can I link it to TaskList and get details based on TaskID from this Notification List?
<Label Text="{Binding How can I link this to show Task details based on the ID??}" />
<!-- Other properties... -->
</StackLayout>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>`
我尝试了这段代码的几个不同的迭代,我尝试搜索过去三个小时,尝试询问 ChatGPT 和 Gemini,但我找不到我要找的东西。我需要有人为我指明正确的方向。
您可以尝试在卡片模型中嵌套
ObservableCollection
。如何检索“今天的任务通知列表”是次要的(您可以查询数据库或其他方式)。但这里的关键是,当您将这些项目添加到卡片的 SubItems
集合中时,UI 将正确绑定并做出响应。
这就是我的意思:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local ="clr-namespace:VariableSubitemsPOC"
x:Class="VariableSubitemsPOC.MainPage">
<ContentPage.BindingContext>
<local:MainPageBindingContext />
</ContentPage.BindingContext>
<Grid
Padding="30,0"
RowDefinitions="70, *">
<Image
Source="dotnet_bot.png"
HeightRequest="70"
Aspect="AspectFit"
VerticalOptions="Center"
SemanticProperties.Description="dot net bot in a race car number eight" />
<CollectionView
Grid.Row="1"
ItemsSource="{Binding Items}"
BackgroundColor="Azure">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame
Padding="10"
Margin="5"
BorderColor="Gray"
CornerRadius="10"
HasShadow="True">
<StackLayout>
<Label Text="{Binding Description}"
FontAttributes="Bold"
FontSize="Medium"
HorizontalOptions="Center" />
<StackLayout>
<StackLayout BindableLayout.ItemsSource="{Binding SubItems}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Description}" FontSize="Small"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
</StackLayout>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
class Card : INotifyPropertyChanged
{
public string? Description
{
get => _description;
set
{
if (!Equals(_description, value))
{
_description = value;
OnPropertyChanged();
}
}
}
string? _description = default;
public ObservableCollection<SubItem>? SubItems { get; set; } = new ObservableCollection<SubItem>();
protected virtual void OnPropertyChanged([CallerMemberName]string? propertyName = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public event PropertyChangedEventHandler? PropertyChanged;
public override string ToString() => Description ?? string.Empty;
}
class SubItem : INotifyPropertyChanged
{
public string? Description
{
get => _description;
set
{
if (!Equals(_description, value))
{
_description = value;
OnPropertyChanged();
}
}
}
string? _description = default;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public event PropertyChangedEventHandler? PropertyChanged;
public override string ToString() => Description ?? string.Empty;
}
public partial class MainPage : ContentPage
{
public MainPage() => InitializeComponent();
}
class MainPageBindingContext
{
public MainPageBindingContext()
{
for (int i = 3; i < 7; i++)
{
Items.Add(new Card
{
Description = DateTime.Now.AddDays(i).ToString("dddd"),
});
}
_ = ExecAddDynamicSubitemsTest();
}
private async Task ExecAddDynamicSubitemsTest()
{
const int TEST_CARD_INDEX = 3;
for (int i = 1; i <= 4; i++)
{
await Task.Delay(1000);
var newTaskDescription = $"Dynamic Task {i}";
Items[TEST_CARD_INDEX].SubItems.Add(new SubItem { Description = newTaskDescription });
}
}
public ObservableCollection<Card> Items { get; } = new ObservableCollection<Card>
{
new Card
{
Description = "Today",
SubItems = new ObservableCollection<SubItem>
{
new SubItem { Description = "Plan the week" },
new SubItem { Description = "Study Econ" },
new SubItem { Description = "Meditate for 10 minutes" },
}
},
new Card
{
Description = "Tomorrow",
SubItems = new ObservableCollection<SubItem>
{
new SubItem { Description = "Go for a morning run" },
new SubItem { Description = "Prepare breakfast" }
}
},
new Card
{
Description = DateTime.Now.AddDays(2).ToString("dddd"),
SubItems = new ObservableCollection<SubItem>
{
new SubItem { Description = "Call a friend" },
new SubItem { Description = "Sort emails" },
new SubItem { Description = "Plan the week ahead" },
new SubItem { Description = "Walk Jeremy's dog" },
new SubItem { Description = "Write in journal" },
}
}
};
}