首页 > 解决方案 > ObservableCollection 不刷新 UI

问题描述

我是 Xamarin 的新手,在 Listview 中刷新数据时遇到问题。我有一些数据和模式的页面,我可以在其中修改它们的值。通过 MessagingCenter 与第一页进行模态通信

我的代码的一些片段:

页:

<ListView ItemsSource="{Binding RecordsList}" HasUnevenRows="True" Grid.Row="1">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <Grid VerticalOptions="StartAndExpand">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="3*"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="30" />
                                </Grid.RowDefinitions>
                                <Label Text="{Binding Name}" Grid.Column="0" Grid.Row="0" VerticalTextAlignment="Center"/>
                                <Label Text="{Binding Result}" Grid.Column="1" Grid.Row="0" VerticalTextAlignment="Center" HorizontalTextAlignment="End" />
                            </Grid>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

视图模型:

    private ObservableCollection<Record> recordsList { get; set; }
    public ObservableCollection<Record> RecordsList
    {
        get { return recordsList; }
        set
        {
            recordsList = value;
            NotifyPropertyChanged("RecordsList");
        }
    }
    MessagingCenter.Subscribe<ObservableCollection<Record>>(this, "update", (records) =>
    {
       RecordsList = records;
    });

我可以修改数据的模式:

            <ListView ItemsSource="{Binding RecordsList, Mode=TwoWay}" HasUnevenRows="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid VerticalOptions="StartAndExpand">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*" />
                                <RowDefinition Height="3*" />
                            </Grid.RowDefinitions>
                            <Label Text="{Binding Name}" Grid.Row="0" VerticalTextAlignment="Center"/>
                            <Entry Text="{Binding Result}" Keyboard="Numeric" Grid.Row="1" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <StackLayout>
            <Button Text="Zapisz" Command="{Binding SaveRecordsCommand}"/>
        </StackLayout>

模态视图模型:

        private readonly INavigation _navigation;
    public ObservableCollection<Record> RecordsList { get; set; }
    public ICommand CloseModalCommand { get; private set; }
    public ICommand SaveRecordsCommand { get; private set; }

    public EditRecordsViewModel(INavigation navigation, ObservableCollection<Record> recordsList)
    {
        _navigation = navigation;
        RecordsList = recordsList;
        CloseModalCommand = new Command(async avatar => await CloseModal());
        SaveRecordsCommand = new Command(async avatar => await SaveRecords());
    }

    private async Task CloseModal()
        => await _navigation.PopModalAsync();

    private async Task SaveRecords()
    {
        ProfilRepository.UpdateRecords(RecordsList);
        MessagingCenter.Send<ObservableCollection<Record>>(RecordsList, "update");
        await CloseModal();
    }

在调试期间 RecordList 被更改但视图没有刷新,这段代码有什么问题?

标签: c#xamarinxamarin.forms

解决方案


如果您设置了正确的绑定,它应该可以工作,我为您编写了一个演示,您可以检查您的代码是否有任何差异以找出问题:

在 xaml 中,与您的代码相同:

<ListView ItemsSource="{Binding RecordsList}" HasUnevenRows="True" Grid.Row="1">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid VerticalOptions="StartAndExpand">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="3*"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30" />
                    </Grid.RowDefinitions>
                    <Label Text="{Binding Name}" Grid.Column="0" Grid.Row="0" VerticalTextAlignment="Center"/>
                    <Button Clicked="Button_Clicked" Text="click to change" Grid.Column="1" Grid.Row="0"  />
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

在后面的代码中:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        ProfilViewModel model = new ProfilViewModel();
        BindingContext = model;
    }

    private void Button_Clicked(object sender, EventArgs e)
    {
        var RecordsList = new ObservableCollection<Record>();

        RecordsList.Add(new Record { Name = "e" });
        RecordsList.Add(new Record { Name = "f" });
        RecordsList.Add(new Record { Name = "g" });

        MessagingCenter.Send<ObservableCollection<Record>>(RecordsList, "update");
    }
}

public class ProfilViewModel : INotifyPropertyChanged
{

    private ObservableCollection<Record> recordsList { get; set; }
    public ObservableCollection<Record> RecordsList
    {
        get { return recordsList; }
        set
        {
            recordsList = value;
            OnPropertyChanged("RecordsList");
        }  
    }

    public ProfilViewModel() {


        recordsList = new ObservableCollection<Record>();

        recordsList.Add(new Record { Name = "a" });
        recordsList.Add(new Record { Name = "b" });
        recordsList.Add(new Record { Name = "c" });


        MessagingCenter.Subscribe<ObservableCollection<Record>>(this, "update", (records) =>
        {
            RecordsList = records;
        });
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

public class Record : INotifyPropertyChanged
{
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    string name { get; set; }
    public string Name
    {
        set
        {
            if (name != value)
            {
                name = value;
                OnPropertyChanged("Name");
            }
        }
        get
        {
            return name;
        }
    }
}

我认为您应该检查的几点是:

  1. RecordsList 中的值在您发送MessagingCenter.Send. 你可以在里面添加一个断点MessagingCenter.Subscribe来检查。
  2. 你在哪里放的MessagingCenter.Subscribe,和我里面的代码一样 public ProfilViewModel(){}
  3. 你的绑定对吗?你INotifyPropertyChangedRecord模型中实现了吗?

推荐阅读