在嵌套的可观察集合中绑定标签的命令属性



我有两个嵌套的可观察集合,第一个是工作日的列表,第二个是这一天的可用时间。我需要有一个按钮才能单独删除这些时间中的任何一个。但无法实现在点击"删除"标签时正确调用命令"删除小时"。到目前为止,我有这个:

代码隐藏

public static ObservableCollection<Calendar> CalendarDays { get; set; } = new ObservableCollection<Calendar>();
public AgendaAutoDispon()
{
InitializeComponent();
InitializeCalendar();
CalendarDays.Add(new Calendar(DateTime.Today));
CalendarDays.Add(new Calendar(DateTime.Today.AddDays(1)));
CalendarDays.Add(new Calendar(DateTime.Today.AddDays(2)));
CollectionViewDatas.BindingContext = CalendarDays;
}

public class Calendar : INotifyPropertyChanged
{
public Picker HourPicker { get; set; } = new Picker();
public ObservableCollection<string> Hours { get; set; } = new();
public ObservableCollection<string> HoursReceipt { get; set; } = new();
public Calendar(DateTime day)
{
Day = day;
for (int i = 6; i <= 22; i++)
{
HoursReceipt.Add((i < 10 ? "0" + i.ToString() : i.ToString()) + ":00");
HoursReceipt.Add((i < 10 ? "0" + i.ToString() : i.ToString()) + ":30");
}
NotifyPropertyChanged("HoursReceipt");
}
private string _DateShow;
public string DateShow
{
get => _DateShow;
set
{
_DateShow = value;
NotifyPropertyChanged("DateShow");
}
}
private DateTime _Day { get; set; }
public DateTime Day
{
get => _Day;
set
{
_Day = value;
switch (value.DayOfWeek)
{
case DayOfWeek.Sunday: WeekDay = "Sunday"; break;
case DayOfWeek.Monday: WeekDay = "Monday"; break;
case DayOfWeek.Tuesday: WeekDay = "Tuesday"; break;
case DayOfWeek.Wednesday: WeekDay = "Wednesday"; break;
case DayOfWeek.Thursday: WeekDay = "Thursday"; break;
case DayOfWeek.Friday: WeekDay = "Friday"; break;
case DayOfWeek.Saturday: WeekDay = "Saturday"; break;
}
DateShow = value.ToString("dd/MM/yyyy");
NotifyPropertyChanged("Day");
}
}
private string _WeekDay;
public string WeekDay
{
get => _WeekDay;
set
{
_WeekDay = value;
NotifyPropertyChanged("WeekDay");
}
}
public string HourChangedEvent
{
set
{
if (!Hours.Contains(value))
{
Hours.Add(value);
Hours = new ObservableCollection<string>(Hours.OrderBy(i => i));
NotifyPropertyChanged("Hours");
}
}
}
public Command RemoveHour
{
get
{
return new Command((arg) => {
Console.WriteLine("I SHOULD REMOVE =====> "+(string)arg);
});
}
}
public event PropertyChangedEventHandler PropertyChanged;
void NotifyPropertyChanged(string propChanged)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propChanged));
}
}

XAML

<CollectionView x:Name="CollectionViewDates" BindingContext="{Binding CalendarDays}" ItemsSource="{Binding .}"
VerticalOptions="Center" Margin="0,10,0,0">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Horizontal" HorizontalItemSpacing="10" />
</CollectionView.ItemsLayout>
<!-- WEEK DAYS -->
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame CornerRadius="15" Padding="0" Margin="5" HasShadow="False" BorderColor="LightGray">
<Grid HeightRequest="300" WidthRequest="200" HorizontalOptions="CenterAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Label Text="{Binding WeekDay}" Grid.Row="0" TextColor="#4D4D4D" FontSize="20"
HorizontalTextAlignment="Center" FontAttributes="Bold" Margin="0,5,0,0" />
<Label Text="{Binding DateShow}" Grid.Row="1" Margin="0,3,0,0" TextColor="#4D4D4D" FontSize="18"
HorizontalTextAlignment="Center" />

<!-- HOURS -->
<CollectionView Grid.Row="3" ItemsSource="{Binding Hours}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" VerticalItemSpacing="5" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid HeightRequest="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>

<Label Grid.Column="0" Text="{Binding .}" HorizontalTextAlignment="Center" />
<Label Grid.Column="1" Text="REMOVE" FontSize="20" TextColor="Red" Padding="0"
HorizontalTextAlignment="Center">

<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding WHAT SHOULD I HAVE HERE??? }"
CommandParameter="{Binding .}" />
</Label.GestureRecognizers>
</Label>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>

</CollectionView>
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>

我必须做什么才能达到绑定的上一个级别,该级别具有命令 RemoveHour?

您可以使用相对绑定

<TapGestureRecognizer
Command="{Binding RemoveHour, Source={RelativeSource AncestorType={x:Type local:Calendar}}}"
CommandParameter="{Binding .}"/>

local:Calendar意味着您需要xmlns:local="..."导入日历视图模型的命名空间,然后才能将日历视图模型用于绑定。

更多信息: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings

我还建议使用常见的 C# 和 MVVM 命名约定,例如为 ViewModel 提供ViewModel后缀,例如 命令的CalendarViewModelRemoveHourCommand

更新

我刚刚注意到您没有正确应用 MVVM 模式。应将Calendar类移动到单独的文件中,并将其设置为 View 代码隐藏BindingContext。代码隐藏不应保存作为业务逻辑一部分的状态或对象和功能,它实际上应该只执行与视图有关的操作。我的解决方案仅在视图的绑定上下文设置为Calendar时才有效,实际上应该是一个名为CalendarViewModel的视图模型,并包含您尝试绑定到的日历日和命令。

最新更新