当我尝试使用 MessagingCenter 从另一个页面填充它来通信两个类时,ListView 没有填满

Posted

技术标签:

【中文标题】当我尝试使用 MessagingCenter 从另一个页面填充它来通信两个类时,ListView 没有填满【英文标题】:ListView not filling up when I try to fill it from another page using MessagingCenter to comunicate both classes 【发布时间】:2020-11-19 18:08:19 【问题描述】:

当用户单击 PageB 中的按钮时,我正在尝试填充或填充在 PageA 中实例化的 ListView。我正在使用 PageB 中的 MessageCenter 发送一条消息,并在 PageA 中调用 MessageCenter.Subscribe() 方法(我想将新 ViewCell 或行添加到 ListView 的页面)......但它不起作用。

我不认为问题来自发送/订阅使用,因为我已经调试了应用程序,并且我传递给 ListiView.ItemSource 属性的集合的大小确实在增长。在这里你可以看到类定义:

PageA类定义:

public partial class WorkoutRoutineTab : ContentPage
    
        public List<Routine> Routines  get; set;  = new List<Routine>();

        public WorkoutRoutineTab()
        
            InitializeComponent();

            routineListView.ItemsSource = Routines;

            MessagingCenter.Subscribe<AddExercisePage, Routine>(this, "FillRoutines", (messageSender, arg) =>
            
                Routines.Add(new Routine(arg.Name, arg.ExerciseList));
                routineListView.ItemsSource = Routines;
            );
        

        private async void NewRoutineButton_Clicked(object sender, EventArgs e)
        
            await DisplayAlert("ALERT", Routines.Count.ToString() , "ok");
            await Navigation.PushAsync(new ExerciseBankTab()  Title = "" );
        

PageA .xaml 文件:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:PumpFit"
             xmlns:custom="clr-namespace:PumpFit.Entity"
             mc:Ignorable="d"
             x:Class="PumpFit.WorkoutRoutineTab"
             Title="Workout"
             BackgroundColor="#343434">

    <StackLayout x:Name="routineStackLayout" Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Center" Margin="20,10">
        <ListView x:Name="routineListView" x:FieldModifier="public" SeparatorColor="#2C2C2C">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid RowDefinitions="2*,*" ColumnDefinitions="*,*">
                            <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Text="Binding custom:Name" TextColor="White" FontSize="Large" FontFamily="Ubuntu"/>
                            <Label Grid.Row="1" Grid.Column="0" Text="Binding custom:TimesDone" TextColor="#9F9F9F" FontSize="Body" FontFamily="Ubuntu"/>
                            <Label Grid.Row="1" Grid.Column="1" Text="Binding custom:TimesDone" TextColor="#9F9F9F" FontSize="Body" FontFamily="Ubuntu"/>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
            <Button x:Name="newRoutineButton" Text="New routine" FontSize="Body" FontFamily="Geo" 
                BackgroundColor="#2C2C2C" TextColor="#87BC72" Clicked="NewRoutineButton_Clicked" />
    </StackLayout> 

</ContentPage>

PageB 类定义:

public partial class AddExercisePage : ContentPage
    
        public Exercise newExercise;

        public AddExercisePage(Exercise selectedExercise)
        
            InitializeComponent();

            newExercise = selectedExercise; 

            nameLabel.Text = newExercise.Name;
        

        private async void CancelButton_Clicked(object sender, EventArgs e)
        
            await Navigation.PopModalAsync();
        

        private void AddButton_Clicked(object sender, EventArgs e)
        
            if(setsEntry.Text != null && repsEntry.Text != null && restTimePicker.SelectedItem != null)
            
                if (int.TryParse(setsEntry.Text, out int sets) && int.TryParse(repsEntry.Text, out int reps) && sets > 0 && reps > 0)
                
                    List<Exercise> newExerciseList = new List<Exercise>()
                    
                        new Exercise(newExercise.Name, newExercise.MuscleGroup, newExercise.ExerciseDifficulty, newExercise.Equipment, newExercise.Description, sets, reps, restTimePicker.SelectedItem.ToString())
                    ;

                    MessagingCenter.Send<AddExercisePage, Routine>(this, "FillRoutines", new Routine(routineNameEntry.Text, newExerciseList));
                
                else
                
                    DisplayAlert("ERROR", "You must only enter positive numbers", "OK");
                
            
            else
            
                DisplayAlert("ERROR", "All fields must be set to add the exercise to the routine", "OK");
            
        
    

任何帮助将不胜感激! :v

【问题讨论】:

【参考方案1】:

问题是你正在使用

public List<Routine> Routines  get; set;  = new List<Routine>();

改成:

public ObservableCollection<Routine> Routines  set; get;  = new ObservableCollection<Routine>();

ListObservableCollection都实现了IList&lt;T&gt;,差别不大,ObservableCollection也实现了INotifyCollectionChanged接口。所以它会在集合发生变化时自动更新UI。

【讨论】:

你说的完全正确,确实是这个问题!非常感谢@Leo Zhu。我认为当您处理必须经常更新的数据时,使用其他集合比使用通用 List 更好吗? 朱问题再次出现。自从您回答问题并且一切正常后,我实际上并没有更改这些文件。但知道它不起作用!我不知道到底发生了什么,你能帮帮我吗? 尝试让您的消息中心订阅 WorkoutRouineTab。 不走运,它仍然是相同的,当使用 WorkoutRoutineTab 订阅时,我传递给 ItemSource 属性的 ObservableCollection 的大小甚至没有增长。如果我理解得很好,当您告诉我使用 WorkoutRoutineTab 订阅时,只是更改了 subscribe 方法的第一个通用参数,对吗?只是确认,但无论如何......仍然无法正常工作:'( 这很奇怪,我的意思是自从它工作以来我所做的唯一新东西是添加一个新的内容页面,当点击 ListView 的任何项目时,我正在将其推送到导航堆栈中,但是这是一个完全不同的事件,我什至没有触及其余的代码。你想看看其他班级吗?

以上是关于当我尝试使用 MessagingCenter 从另一个页面填充它来通信两个类时,ListView 没有填满的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.Forms之MessagingCenter

当我尝试从另一个活动中获取数据时,应用程序返回上一页

.NET MAUI实战 MessagingCenter

当我从另一个类调用数组时,数组不会更新

从另一个线程向 QSerialPort 发送数据

无法从另一个孩子读取一个孩子写入的共享内存