.net MAUI 中的 ObservableCollection 问题

Jiale Xue - MSFT 34,356 信誉分 Microsoft 供应商
2024-03-21T08:58:59.0866667+00:00

当我打开应用程序时,它会读取 sqlite 数据库并填充 ListView,但是当我向通讯簿添加新条目(通过转到“新地址页面”)时,它不会刷新 ListView,直到我退出应用程序并返回。

主页 XAML

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"  
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"  
                 x:Class="MVVMAddressBook.Views.MainPage"  
                 xmlns:nav="clr-namespace:MVVMAddressBook.ViewModels"  
                 Title="MainPage">  
        <Grid>  
            <Grid.RowDefinitions>  
                <RowDefinition Height=".9*"></RowDefinition>  
                <RowDefinition Height=".1*"></RowDefinition>  
            </Grid.RowDefinitions>  
            <VerticalStackLayout Grid.Row="0">  
                <Label Text="Address Book"   
                   HorizontalOptions="Center">  
                </Label>  
                <ListView x:Name="listx"   
                          ItemsSource="{Binding AddressList}"  
                          VerticalScrollBarVisibility="Always"  
                          Grid.Row="0">  
                    <ListView.ItemTemplate>  
                        <DataTemplate>  
                            <ViewCell>  
                                <Grid Margin="10,0,10,0">  
                                    <Grid.RowDefinitions>  
                                        <RowDefinition Height="Auto" />  
                                    </Grid.RowDefinitions>  
                                    <Grid.ColumnDefinitions>  
                                        <ColumnDefinition Width="30*" />  
                                        <ColumnDefinition Width="30*" />  
                                        <ColumnDefinition Width="30*" />  
                                    </Grid.ColumnDefinitions>  
                                    <Label  Grid.Column="0" Text="{Binding ID}"/>  
                                    <Label  Grid.Column="1" Text="{Binding FirstName}"/>  
                                    <Label Grid.Column="2" Text="{Binding LastName}"/>  
                                </Grid>  
                            </ViewCell>  
                        </DataTemplate>  
                    </ListView.ItemTemplate>  
                </ListView>  
            </VerticalStackLayout>  
            <Button Text="Add New Address"  
                    HeightRequest="40"  
                    Grid.Row="1"   
                    Command="{Binding newAddressComand}"  
                    HorizontalOptions="Center">  
            </Button>  
        </Grid>  
    </ContentPage>  

MainPage 代码隐藏

using MVVMAddressBook.Models;  
using MVVMAddressBook.ViewModels;  
  
namespace MVVMAddressBook.Views;  
  
public partial class MainPage : ContentPage  
{  
 public MainPage()  
 {  
 InitializeComponent();                 
       BindingContext = new MainPageViewModel(Navigation);  
    }  
  
}  
  

“视图模型”页

namespace MVVMAddressBook.ViewModels  
{  
    [AddINotifyPropertyChangedInterface]  
    public class MainPageViewModel  
    {  
        public ICommand newAddressComand => new Command(() => GetCommand());  
        public INavigation Navigation { get; set; }  
  
        SQLiteConnection _connection;  
                  
        private ObservableCollection<Addresses> addressList;  
  
        public ObservableCollection<Addresses> AddressList  
        {  
            get { return addressList; }  
            set { addressList = value; }  
        }  
  
  
        public MainPageViewModel(INavigation navigation)  
        {            
            this.Navigation = navigation;  
            PopulateList();  
        }  
          
        // Go to new address page  
        public async void GetCommand()  
        {  
            await Navigation.PushAsync(new NewAddress());  
        }  
  
        public void PopulateList()  
        {  
            try  
            {                  
                var dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "address.db");  
                _connection = new SQLiteConnection(dbPath);  
                var result = _connection.CreateTable<Addresses>();  
            }  
            catch (Exception ex)  
            {  
                Debug.WriteLine("Error = " + ex.Message);  
            }  
            AddressList = new ObservableCollection<Addresses>(_connection.Table<Addresses>().ToList());    
        }  
    }  
}  

将地址添加到 AddressList 后,它不会显示在 ListView 中。下面是 NewAddressViewModel 的代码。

谢谢:-)

namespace MVVMAddressBook.ViewModels  
{  
    [AddINotifyPropertyChangedInterface]  
    public class NewAddressViewModel : IContractAddresses  
    {  
        public ICommand saveCommand => new Command(() => GetSaveCommand());  
        public ICommand cancelCommand => new Command(() => GetCancelCommand());  
  
        public string FirstNameEntry { get; set; }    
        public string LastNameEntry { get; set; }  
        public string PhoneNumberEntry { get; set; }  
        public string AddressEntry { get; set; }  
        public string CityEntry { get; set; }  
        public string GenderEntry { get; set; }  
  
        SQLiteConnection _connection;  
        public INavigation Navigation { get; set; }  
        //Constructor  
        public NewAddressViewModel(INavigation navigation )  
        {  
            this.Navigation = navigation;  
            try  
            {  
                //Initialize database and create table  
                var dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "address.db");  
                _connection = new SQLiteConnection(dbPath);  
                var result = _connection.CreateTable<Addresses>();  
            }  
            catch (Exception ex)  
            {  
                Debug.WriteLine("Error1 = " + ex.Message);  
            }  
        }  
  
        // Write to Database  
        public void GetSaveCommand()  
        {  
            Addresses addresses = new Addresses()  
            {  
                FirstName = FirstNameEntry,  
                LastName = LastNameEntry,  
                PhoneNumber = PhoneNumberEntry,  
                Address = AddressEntry,  
                City = CityEntry,  
                Gender = GenderEntry  
            };  
            try  
            {  
                var result = addresses;  
                var res = AddContact(addresses);  
                var res1 = _connection.Table<Addresses>().Count();  
                  
                var resk = GetContact(0);                  
            }  
            catch(Exception ex)  
            {  
                Debug.WriteLine("Error: " + ex.Message);   
            }  
        }  
  
  
        public void GetCancelCommand()  
        {  
            Debug.WriteLine("Cancel");  
            _connection.DropTable<Addresses>();  
            Navigation.PopAsync();  
        }  
          
  
        public Task<IEnumerable<Addresses>> GetContactsAsync()  
        {  
            throw new NotImplementedException();  
        }  
  
        public Addresses GetContact(int id)  
        {  
            try  
            {  
                var resu = _connection.Table<Addresses>().ToList();                  
            }  
            catch(Exception ex)  
            {  
                Debug.WriteLine("Get contact error = " + ex.Message);  
            }             
            return null;              
        }  
  
        public int AddContact(Addresses address)         
        {  
            try  
            {  
               int ret = _connection.Insert(address);  
                Debug.WriteLine("Insert error = " );  
                MainPageViewModel mainPageViewModel = new MainPageViewModel(null);  
                mainPageViewModel.PopulateList();  
            }  
            catch(Exception ex)  
            {       
                Debug.WriteLine("Insert error = " + ex.Message);                  
            }  
            return 0;  
        }  
  
        public Task UpdateContact(Addresses address)  
        {  
            throw new NotImplementedException();  
        }  
  
        public Task DeleteContact(Addresses address)  
        {  
            throw new NotImplementedException();  
        }  
          
    }  
}  

地址模型

public class Addresses  
    {  
        [PrimaryKey, AutoIncrement]  
        public int ID { get; set; }  
        public string FirstName { get; set; }  
        public string LastName { get; set; }  
        public string PhoneNumber { get; set; }  
        public string Address { get; set; }  
        public string City { get; set; }  
        public string Gender { get; set; }  
    }  

Note:此问题总结整理于: Issue with ObservableCollection in .net MAUI

.NET MAUI
.NET MAUI
一种 Microsoft 开源框架,用于构建跨移动设备、平板电脑、台式机的原生设备应用程序。
41 个问题
C#
C#
一种面向对象的类型安全的编程语言,它起源于 C 语言系列,包括对面向组件的编程的支持。
114 个问题
0 个注释 无注释
{count} 票

接受的答案
  1. Hui Liu-MSFT 40,786 信誉分 Microsoft 供应商
    2024-03-21T09:38:44.61+00:00

    如果要在导航回 MainPage 时更新 Listview。您需要在 MainPage 中添加 EventToCommandBehavior(注意:在使用它之前,您需要安装 CommunityToolkit.Maui nuget 包)。当 MainPage 事件被执行时,你可以执行一个 在你的 .AppearingcommandMainPageViewModel

    以下是实现它的步骤。

    首先,在 Nuget 包管理器中搜索(单击“工具”->“Nuget 包管理器”->“管理解决方案的 nuget 包”)。安装它,然后打开你,在方法上添加以下代码以初始化 CommunityToolkit.MauiCommunityToolkit.MauiMauiProgram.csCreateMauiApp

       builder.UseMauiApp<App>().UseMauiCommunityToolkit();  
    

    然后我们可以添加 MainPage。添加前缀和EventToCommandBehaviorxmlns:behaviorsContentPage.Behaviors

       <ContentPage   
       ....  
                    xmlns:behaviors="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"  
       ....  
          >  
       <ContentPage.Behaviors>  
               <behaviors:EventToCommandBehavior EventName="Appearing" Command="{Binding PageAppearingCommand}">  
               </behaviors:EventToCommandBehavior>         
           </ContentPage.Behaviors>  
    

    最后实现方法:清除 AddressList,从 SQLite DB 中获取最新数据,并将最新数据填充到 AddressList 中。PageAppearingCommandMainPageViewModel.cs

       public ICommand PageAppearingCommand => new Command(() => GetPopulateList());  
         
           private void GetPopulateList()  
           {  
               List<Addresses>  addresses= _connection.Table<Addresses>().ToList();  
               AddressList.Clear();  
               foreach (Addresses address in addresses)  
               {  
                   AddressList.Add(address);  
               }  
           }  
    
    
    

    如果答案是正确的,请点击“接受答案”并点赞。 如果您对此答案还有其他疑问,请点击“评论”。

    注意:如果您想接收相关电子邮件,请按照我们的文档中的步骤启用电子邮件通知 此线程的通知。

    1 个人认为此答案很有帮助。
    0 个注释 无注释

0 个其他答案

排序依据: 非常有帮助