ViewModel 类中未设置对象,控制直接从数据访问类移动到 View

Posted

技术标签:

【中文标题】ViewModel 类中未设置对象,控制直接从数据访问类移动到 View【英文标题】:Object is not set in ViewModel class and control is directly move from data access class to View 【发布时间】:2016-07-25 07:27:48 【问题描述】:

我想从 AboutUs 表中获取第一条记录并显示为内容标签。

我在 MVVM 模式中创建了 4 个类。

首先是模型类 AboutUs.cs

[Table("tblAboutUs")]
    public class AboutUs
    
        [PrimaryKey, AutoIncrement, NotNull]
        public int IDP  get; set; 
        public string Content  get; set; 
    

其次是数据访问类

SQLiteAboutUs.cs

public class SQLiteAboutUs
    
        private static readonly AsyncLock Mutex = new AsyncLock();
        private SQLiteAsyncConnection dbConn;

        public int StatusCode  get; set; 

        public SQLiteAboutUs(ISQLitePlatform sqlitePlatform, string dbPath)
        

            if (dbConn == null)
            
                var connectionFunc = new Func<SQLiteConnectionWithLock>(() =>
                    new SQLiteConnectionWithLock
                    (
                        sqlitePlatform,
                        new SQLiteConnectionString(dbPath, storeDateTimeAsTicks: false)
                    ));

                dbConn = new SQLiteAsyncConnection(connectionFunc);
                dbConn.CreateTableAsync<Model.AboutUs>();
            
        

        public SQLiteAboutUs()
        
        
        public async Task Save(Model.AboutUs content)
        
            using (await Mutex.LockAsync().ConfigureAwait(false))
            
                StatusCode = 0;


            await dbConn.InsertAsync(new Model.AboutUs  Content = content.Content );
            StatusCode = 1;
        

        //For Get first Row from Table
        public async Task<Model.AboutUs> GetAllData()
        
            return await dbConn.Table<Model.AboutUs>().Where(x => x.IDP == 1).FirstOrDefaultAsync();
        
    

第三类 ViewModel 类

AboutUsViewModel.cs

public class AboutUsViewModel
    
        readonly SQLiteAboutUs _db;
        public string AboutUsContent  get; set; 

        //public string AboutUs;  
        public AboutUsViewModel()
        
            _db = new SQLiteAboutUs();
        
        public async void FirstRecord()
        
            Model.AboutUs obj = await _db.GetAllData();
            this.AboutUsContent = obj.Content;
        
    

第四个是我的 xaml 页面的代码隐藏文件。

AboutUs.xaml.cs

public partial class AboutUs : ContentPage
    
        readonly AboutUsViewModel aboutUsViewModel;
        public AboutUs()
        
            InitializeComponent();

            aboutUsViewModel = new AboutUsViewModel();

            aboutUsViewModel.FirstRecord();

            lblContent.Text = aboutUsViewModel.AboutUsContent;
        
    

我有调试代码,但问题是在 FirstRecord Method 对象中的 AboutUsViewModel.cs 类中无法设置,这就是为什么 AboutUsContent 字符串属性也未设置的原因。

我不明白为什么我的调试器直接从 SQLiteAboutUs.cs 中的 GetAllData() 方法跳转到视图文件后面代码中的 label.text?

【问题讨论】:

这里究竟是什么?你确定 dbConn 不为空吗?它发生在我身上很多次。您也可以尝试分配这样的变量吗? var result= await dbConn.Table().Where(x => x.IDP == 1).FirstOrDefaultAsync();可能有一个 try catch,只是为了确定是 FirstOrDefaultAsync 造成问题还是返回类型造成问题? 【参考方案1】:

欢迎来到异步的奇妙世界。我鼓励你仔细阅读 await 是如何工作的:How and When to use `async` and `await`

这不是阻塞调用。因此,您创建了 AboutUs 视图。它创建 ViewModel AboutUsViewModel。它调用了

aboutUsViewModel.FirstRecord();

但不等待调用完成(不要忘记您将 FirstRecord 函数标记为异步...)

所以它调用

Model.AboutUs obj = await _db.GetAllData();

并且因为await操作符而直接返回给调用者。 所以直接跳转到

lblContent.Text = aboutUsViewModel.AboutUsContent;

你想要的是类似的东西

await aboutUsViewModel.FirstRecord();

在转到下一行之前等待呼叫完成。但是你当然不能这样做,因为你在一个构造函数中,你不能有一个异步构造函数。无论如何,在构造函数中调用数据库(或者实际上任何可能失败的东西)都是一种不好的做法。

我建议您只在构造函数中使用 InitializeComponent(),然后使用类似于视图的 OnDataLoaded() 事件的东西来执行带有等待的异步调用。

希望对你有帮助。

【讨论】:

谢谢你鼓励我。不是我看到实际问题。我在 xamarin.forms 中找不到 OnDataLoaded() 方法。所以我正在使用 OnAppearing() 方法。 但问题是当 GetAllData 方法调用它给我错误“对象引用未设置为对象的实例”。 OnAppearing 可能很快就会出现,您应该稍后再寻找另一个事件,或者只是手动调用诸如初始化函数之类的东西。

以上是关于ViewModel 类中未设置对象,控制直接从数据访问类移动到 View的主要内容,如果未能解决你的问题,请参考以下文章

Pycharm 检查未标记从存根对象继承的类中未解析的引用

指令的angularjs typescript控制器类中未定义的范围变量

来自商店的数据中未定义的数组中的 Vue.js 对象

无法从ViewModel向用户显示协程错误消息

从事件更新 Viewmodel - PropertyChangedEventHandler 为空?

如何从 ViewModel 对象填充选择器,设置为第一个元素的初始状态并处理选择选择器项的操作