xamarin 系结巢状ObservableCollections中Label的Command属性

bqf10yzr  于 2022-12-07  发布在  其他
关注(0)|答案(1)|浏览(130)

我有两个嵌套的可观察的集合,第一个是工作日的列表,第二个是这一天的可用小时。我需要一个按钮,可以单独删除这些小时中的任何一个。但不能实现命令“RemoveHour”被正确调用时,“REMOVE”标签被点击。我有这个到目前为止:
程式码后置

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?

zed5wv10

zed5wv101#

You can use a Relative Binding:

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

The local:Calendar means you need to import the namespace of your Calendar ViewModel as xmlns:local="..." before you can use the Calendar ViewModel for the binding.
More info: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings
I would also recommend using common C# and MVVM naming conventions, such as giving a ViewModel the ViewModel postfix, e.g. CalendarViewModel or RemoveHourCommand for a Command.

Update

I've just noticed that you're not applying the MVVM pattern correctly. You should move your Calendar class to a separate file and set it as the BindingContext of your View's code-behind. The code-behind should not hold state or objects and functionality that are part of the Business Logic, it should really just do things concerning the View. My solution only works if the BindingContext of the View is set to the Calendar , which should actually be a ViewModel called CalendarViewModel and contain the CalendarDays and the Command your trying to bind to.

相关问题